c829f78984
- Opprettet Flutter-prosjekt med alle nødvendige avhengigheter - Implementert datamodeller (User, TimeRegistration, TariffProfile, Deviation, AuditLog) - Implementert tjenester (AuthService, TimeService) - Implementert Riverpod providers for state management - Opprettet autentiseringsskjermer (login, signup, reset password) - Opprettet hjemmeskjerm med timer-funksjonalitet - Opprettet placeholder-skjermer for historikk, rapporter og profil - Lagt til norsk dokumentasjon i README
196 lines
5.4 KiB
Dart
196 lines
5.4 KiB
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
|
|
class NightWorkRules {
|
|
final int startHour; // e.g., 21 for 9 PM
|
|
final int endHour; // e.g., 6 for 6 AM
|
|
final int maxNightHours;
|
|
|
|
NightWorkRules({
|
|
required this.startHour,
|
|
required this.endHour,
|
|
required this.maxNightHours,
|
|
});
|
|
|
|
factory NightWorkRules.fromMap(Map<String, dynamic> map) {
|
|
return NightWorkRules(
|
|
startHour: map['startHour'] ?? 21,
|
|
endHour: map['endHour'] ?? 6,
|
|
maxNightHours: map['maxNightHours'] ?? 0,
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toMap() {
|
|
return {
|
|
'startHour': startHour,
|
|
'endHour': endHour,
|
|
'maxNightHours': maxNightHours,
|
|
};
|
|
}
|
|
}
|
|
|
|
class TariffRules {
|
|
final int maxDailyHours;
|
|
final int maxWeeklyHours;
|
|
final int minDailyRest; // in minutes
|
|
final int minWeeklyRest; // in minutes
|
|
final bool useAverageCalculation;
|
|
final int? averagePeriodWeeks;
|
|
final int? maxAverageHours;
|
|
final NightWorkRules? nightWorkRules;
|
|
|
|
TariffRules({
|
|
required this.maxDailyHours,
|
|
required this.maxWeeklyHours,
|
|
required this.minDailyRest,
|
|
required this.minWeeklyRest,
|
|
this.useAverageCalculation = false,
|
|
this.averagePeriodWeeks,
|
|
this.maxAverageHours,
|
|
this.nightWorkRules,
|
|
});
|
|
|
|
factory TariffRules.fromMap(Map<String, dynamic> map) {
|
|
return TariffRules(
|
|
maxDailyHours: map['maxDailyHours'] ?? 9,
|
|
maxWeeklyHours: map['maxWeeklyHours'] ?? 40,
|
|
minDailyRest: map['minDailyRest'] ?? 660, // 11 hours
|
|
minWeeklyRest: map['minWeeklyRest'] ?? 2100, // 35 hours
|
|
useAverageCalculation: map['useAverageCalculation'] ?? false,
|
|
averagePeriodWeeks: map['averagePeriodWeeks'],
|
|
maxAverageHours: map['maxAverageHours'],
|
|
nightWorkRules: map['nightWorkRules'] != null
|
|
? NightWorkRules.fromMap(map['nightWorkRules'])
|
|
: null,
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toMap() {
|
|
return {
|
|
'maxDailyHours': maxDailyHours,
|
|
'maxWeeklyHours': maxWeeklyHours,
|
|
'minDailyRest': minDailyRest,
|
|
'minWeeklyRest': minWeeklyRest,
|
|
'useAverageCalculation': useAverageCalculation,
|
|
'averagePeriodWeeks': averagePeriodWeeks,
|
|
'maxAverageHours': maxAverageHours,
|
|
'nightWorkRules': nightWorkRules?.toMap(),
|
|
};
|
|
}
|
|
}
|
|
|
|
class TariffProfile {
|
|
final String id;
|
|
final String name;
|
|
final String description;
|
|
final String organizationId;
|
|
final TariffRules rules;
|
|
final bool isDefault;
|
|
final bool isActive;
|
|
final DateTime createdAt;
|
|
final DateTime updatedAt;
|
|
|
|
TariffProfile({
|
|
required this.id,
|
|
required this.name,
|
|
required this.description,
|
|
required this.organizationId,
|
|
required this.rules,
|
|
this.isDefault = false,
|
|
this.isActive = true,
|
|
required this.createdAt,
|
|
required this.updatedAt,
|
|
});
|
|
|
|
factory TariffProfile.fromFirestore(DocumentSnapshot doc) {
|
|
final data = doc.data() as Map<String, dynamic>;
|
|
return TariffProfile(
|
|
id: doc.id,
|
|
name: data['name'] ?? '',
|
|
description: data['description'] ?? '',
|
|
organizationId: data['organizationId'] ?? '',
|
|
rules: TariffRules.fromMap(data['rules'] ?? {}),
|
|
isDefault: data['isDefault'] ?? false,
|
|
isActive: data['isActive'] ?? true,
|
|
createdAt: (data['createdAt'] as Timestamp).toDate(),
|
|
updatedAt: (data['updatedAt'] as Timestamp).toDate(),
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toFirestore() {
|
|
return {
|
|
'name': name,
|
|
'description': description,
|
|
'organizationId': organizationId,
|
|
'rules': rules.toMap(),
|
|
'isDefault': isDefault,
|
|
'isActive': isActive,
|
|
'createdAt': Timestamp.fromDate(createdAt),
|
|
'updatedAt': Timestamp.fromDate(updatedAt),
|
|
};
|
|
}
|
|
|
|
TariffProfile copyWith({
|
|
String? name,
|
|
String? description,
|
|
String? organizationId,
|
|
TariffRules? rules,
|
|
bool? isDefault,
|
|
bool? isActive,
|
|
DateTime? updatedAt,
|
|
}) {
|
|
return TariffProfile(
|
|
id: id,
|
|
name: name ?? this.name,
|
|
description: description ?? this.description,
|
|
organizationId: organizationId ?? this.organizationId,
|
|
rules: rules ?? this.rules,
|
|
isDefault: isDefault ?? this.isDefault,
|
|
isActive: isActive ?? this.isActive,
|
|
createdAt: createdAt,
|
|
updatedAt: updatedAt ?? this.updatedAt,
|
|
);
|
|
}
|
|
|
|
// Predefined profiles
|
|
static TariffProfile createDefaultAML(String organizationId) {
|
|
return TariffProfile(
|
|
id: 'default_aml',
|
|
name: 'Ingen tariffavtale (AML Standard)',
|
|
description: 'Standard arbeidsmiljøloven uten tariffavtale',
|
|
organizationId: organizationId,
|
|
rules: TariffRules(
|
|
maxDailyHours: 9,
|
|
maxWeeklyHours: 40,
|
|
minDailyRest: 660, // 11 hours
|
|
minWeeklyRest: 2100, // 35 hours
|
|
),
|
|
isDefault: true,
|
|
isActive: true,
|
|
createdAt: DateTime.now(),
|
|
updatedAt: DateTime.now(),
|
|
);
|
|
}
|
|
|
|
static TariffProfile createTariffA(String organizationId) {
|
|
return TariffProfile(
|
|
id: 'tariff_a',
|
|
name: 'Tariffavtale A',
|
|
description: 'Tariffavtale med utvidet arbeidstid og gjennomsnittsberegning',
|
|
organizationId: organizationId,
|
|
rules: TariffRules(
|
|
maxDailyHours: 10,
|
|
maxWeeklyHours: 48,
|
|
minDailyRest: 660, // 11 hours
|
|
minWeeklyRest: 2100, // 35 hours
|
|
useAverageCalculation: true,
|
|
averagePeriodWeeks: 8,
|
|
maxAverageHours: 48,
|
|
),
|
|
isDefault: false,
|
|
isActive: true,
|
|
createdAt: DateTime.now(),
|
|
updatedAt: DateTime.now(),
|
|
);
|
|
}
|
|
}
|