393 lines
12 KiB
Markdown
393 lines
12 KiB
Markdown
# Zeiterfassung
|
||
|
||
Eine Full-Stack-Zeiterfassungsanwendung, entwickelt mit Node.js, Express, SQLite und containerisiert mit Docker.
|
||
|
||
<details>
|
||
<summary><b>📸 Screenshots</b></summary>
|
||
|
||

|
||
*Hauptansicht mit Timer und Monatsübersicht*
|
||
|
||

|
||
*Detaillierte Statistiken und Urlaubsverwaltung*
|
||
|
||

|
||
*Eintragsbearbeitung und Bulk-Operationen*
|
||
|
||
</details>
|
||
|
||
## Funktionen
|
||
|
||
### ⏱️ Zeiterfassung
|
||
- **Live-Timer mit automatischen Pausen**: Start/Stop-Timer erfasst die tägliche Arbeitszeit
|
||
- Automatische Pausen nach 6h (30 Min) oder 9h (45 Min) gemäß deutschem Arbeitszeitgesetz
|
||
- Rundung auf 15-Minuten-Intervalle
|
||
- Timer persistiert über Seiten-Reloads
|
||
- Manuelle Startzeit-Eingabe möglich
|
||
- Visueller Indikator (blinkendes Uhr-Icon) bei laufendem Timer
|
||
- **Flexible Eingabemodi**:
|
||
- Manuelle Eingabe (Datum, Start, Ende, Pause)
|
||
- Inline-Bearbeitung direkt in der Tabelle
|
||
- Schnelles Hinzufügen von Einträgen über Monatsansicht
|
||
- **Arbeitsort-Tracking**: Büro oder Home-Office pro Eintrag
|
||
- **Sondereinträge**:
|
||
- Urlaubstage (werden nicht vom Saldo abgezogen)
|
||
- Gleittage (ziehen 8h vom Saldo ab)
|
||
|
||
### 📊 Intelligente Berechnungen
|
||
- **Automatische Pausenberechnung** (deutsches Arbeitszeitgesetz)
|
||
- **10-Stunden-Cap** für maximale Nettoarbeitszeit pro Tag
|
||
- **Live-Statistiken** mit laufendem Timer:
|
||
- Soll-Stunden (basierend auf Arbeitstagen)
|
||
- Ist-Stunden (inkl. aktuell laufender Timer)
|
||
- Monatssaldo + Gesamtsaldo mit Vormonatsübertrag
|
||
- Arbeitstage-Zählung
|
||
- **Urlaubsverwaltung**:
|
||
- Konfigurierbares Jahres-Kontingent
|
||
- Tracking: Genommen, Geplant, Verfügbar
|
||
- Automatische Jahresberechnung
|
||
|
||
### 🗓️ Bundesland-spezifische Feiertage
|
||
- **16 Bundesländer** mit korrekten regionalen Feiertagen
|
||
- **Persistente Einstellung** (gespeichert in Datenbank)
|
||
- **Kollisionserkennung**: Warnung bei Feiertagen mit bestehenden Einträgen
|
||
- **Alle Feiertage**: Bundeseinheitlich + regional (z.B. Fronleichnam, Reformationstag)
|
||
|
||
### 📅 Monatsansicht & Navigation
|
||
- **Vollständiger Monatskalender** mit allen Tagen
|
||
- **Intuitive Farbcodierung**:
|
||
- 🟢 Grün: Home-Office
|
||
- 🟡 Gelb: Urlaub
|
||
- 🔵 Cyan: Gleittage
|
||
- 🔴 Rot: Fehlende Arbeitstage
|
||
- ⚫ Grau: Wochenenden
|
||
- 🔵 Blau: Feiertage (mit Namen)
|
||
- **Navigation**: Vor/Zurück-Buttons zum Monatswechsel
|
||
- **Auto-Fill**: Automatisches Befüllen des Monats mit Standard-Arbeitszeiten (9:00-17:30)
|
||
- **Quick-Actions**: Plus-Buttons für schnelles Hinzufügen von Einträgen
|
||
|
||
### ⚡ Bulk-Operationen
|
||
- **Mehrfachauswahl-Modus** mit Checkboxen
|
||
- **Bulk-Aktionen**:
|
||
- Standort setzen (Büro/Home)
|
||
- Urlaub eintragen
|
||
- Gleitzeit eintragen
|
||
- Löschen
|
||
- **Funktioniert in beiden Ansichten** (Monatsansicht + Filteransicht)
|
||
|
||
### 🔍 Filter & Export
|
||
- **Zeitraum-Filter**: Von/Bis-Datum (bleibt bei Bulk-Aktionen erhalten)
|
||
- **Getrennte Ansichten**: Monatsnavigation wird bei Filter-Ansicht ausgeblendet
|
||
- **CSV-Export (Alle)**: Alle Einträge im gewählten Zeitraum
|
||
- Spalten: Datum, Start, Ende, Pause (Min), Netto (h), Arbeitsort, Abweichung (h)
|
||
- **CSV-Export (Abweichungen)**: Nur Tage ≠ 8,0h
|
||
- Ideal für Gleitzeit-Nachweise
|
||
- **PDF-Export**:
|
||
- **Monats-Export**: Exportiert aktuellen Monat als formatierten PDF
|
||
- **Bulk-Export**: Exportiert ausgewählte Einträge (im Bulk-Modus)
|
||
- Professionelles Layout mit Mitarbeiter-Info und Statistiken
|
||
- Automatische Tabelle mit allen Einträgen
|
||
- Deutsche Formatierung (Datum, Währung, Dezimalstellen)
|
||
- **Deutsches Format**: Semikolon-getrennt (CSV), Komma-Dezimal
|
||
|
||
### 💾 Datenbank-Management
|
||
- **Datenbank-Export**: Vollständiger Export aller Daten als JSON
|
||
- Enthält alle Einträge und Einstellungen
|
||
- Versioniert für Kompatibilität
|
||
- Zeitstempel im Dateinamen
|
||
- **Datenbank-Import**: Wiederherstellen aus JSON-Backup
|
||
- Validierung der Datenstruktur
|
||
- Bestätigungs-Dialog vor Überschreiben
|
||
- Löscht alte Daten vor Import
|
||
- Importiert Einträge und Einstellungen
|
||
- **Instanz-Migration**: Einfaches Wechseln zwischen Servern/Instanzen
|
||
|
||
### 🎨 Modernes UI/UX
|
||
- **Premium Design**: Glass-Morphism, Gradients, Schatten, Animationen
|
||
- **Responsive**: Desktop, Tablet, Mobile
|
||
- **Dark Mode**: Augenschonendes dunkles Design
|
||
- **Toast-Benachrichtigungen**: Visuelles Feedback
|
||
- **Icons**: Lucide Icons für klare Symbolik
|
||
- **Flatpickr**: Touch-optimierte Datums-/Zeit-Picker
|
||
|
||
## 🏗️ Technologie-Stack
|
||
|
||
**Backend:**
|
||
- Node.js 18+ mit Express.js
|
||
- SQLite (better-sqlite3) für dateibasierte Persistenz
|
||
- Modulare Architektur (config, utils, routes)
|
||
|
||
**Frontend:**
|
||
- Vanilla JavaScript (ES6+)
|
||
- Tailwind CSS (CDN)
|
||
- Lucide Icons
|
||
- Flatpickr (Datums-/Zeit-Picker)
|
||
- jsPDF mit autoTable Plugin (PDF-Generierung)
|
||
|
||
**Infrastructure:**
|
||
- Docker & Docker Compose
|
||
- Multi-Stage Build für optimierte Images
|
||
- Gitea Actions CI/CD für automatische Builds
|
||
- Gitea Container Registry für Image-Hosting
|
||
|
||
## 📁 Projektstruktur
|
||
|
||
```
|
||
timetracker/
|
||
├── server.js # Express Entry Point
|
||
├── db/
|
||
│ ├── schema.sql # Datenbankschema
|
||
│ └── timetracker.db # SQLite Datenbank (generiert)
|
||
├── public/
|
||
│ ├── index.html # Single-Page Application
|
||
│ ├── favicon.svg # App Icon
|
||
│ └── js/
|
||
│ ├── state.js # Globaler State
|
||
│ ├── utils.js # Hilfsfunktionen
|
||
│ ├── holidays.js # Feiertagsberechnung
|
||
│ ├── api.js # Backend-Kommunikation
|
||
│ └── main.js # Hauptlogik (~3700 Zeilen)
|
||
├── .gitea/workflows/ # CI/CD Workflows
|
||
│ └── docker-build.yml # Docker Build & Push
|
||
├── media/screenshots/ # App-Screenshots
|
||
├── Dockerfile # Container-Image
|
||
├── docker-compose.yml # Orchestrierung
|
||
└── package.json
|
||
```
|
||
|
||
## ⚙️ Deutsche Arbeitszeitregelungen
|
||
|
||
Die App implementiert deutsches Arbeitszeitgesetz (ArbZG):
|
||
|
||
- **> 6h Arbeit** → 30 Min Pause (automatisch)
|
||
- **> 9h Arbeit** → 45 Min Pause (automatisch)
|
||
- **Maximale Nettoarbeitszeit**: 10,0h pro Tag
|
||
- **Rundung**: Alle Zeiten auf 15-Minuten-Intervalle
|
||
|
||
## 🚀 Installation & Ausführung
|
||
|
||
### <20> Option 1: Vorgefertigtes Docker Image (Empfohlen)
|
||
|
||
**Voraussetzungen:** Docker (& Docker Compose optional)
|
||
|
||
```bash
|
||
# Image pullen (public registry, kein Login nötig)
|
||
docker pull gitea.fx-se.de/maggot/timetracker:latest
|
||
|
||
# Container starten
|
||
docker run -d \
|
||
-p 3000:3000 \
|
||
-v $(pwd)/db:/app/db \
|
||
--name timetracker \
|
||
gitea.fx-se.de/maggot/timetracker:latest
|
||
```
|
||
|
||
**Oder mit docker-compose.yml:**
|
||
```yaml
|
||
version: '3.8'
|
||
services:
|
||
app:
|
||
image: gitea.fx-se.de/maggot/timetracker:latest
|
||
ports:
|
||
- "3000:3000"
|
||
volumes:
|
||
- ./db:/app/db
|
||
restart: unless-stopped
|
||
```
|
||
|
||
```bash
|
||
# Starten
|
||
docker-compose up -d
|
||
|
||
# Logs
|
||
docker-compose logs -f
|
||
|
||
# Stoppen
|
||
docker-compose down
|
||
|
||
# Stoppen + Daten löschen
|
||
docker-compose down -v
|
||
```
|
||
|
||
**App läuft auf:** `http://localhost:3000`
|
||
|
||
### 🔨 Option 2: Docker (manuell bauen)
|
||
|
||
```bash
|
||
# Repository klonen
|
||
git clone https://gitea.fx-se.de/maggot/timetracker.git
|
||
cd timetracker
|
||
|
||
# Image bauen
|
||
docker build -t zeiterfassung .
|
||
|
||
# Container starten (mit Daten-Persistenz)
|
||
docker run -p 3000:3000 -v $(pwd)/db:/app/db zeiterfassung
|
||
```
|
||
|
||
### 💻 Option 3: Lokal (ohne Docker)
|
||
|
||
**Voraussetzungen:** Node.js 18+
|
||
|
||
```bash
|
||
# Repository klonen
|
||
git clone https://gitea.fx-se.de/maggot/timetracker.git
|
||
cd timetracker
|
||
|
||
npm install
|
||
npm start
|
||
```
|
||
|
||
**App läuft auf:** `http://localhost:3000`
|
||
|
||
## 📤 Export-Funktionen
|
||
|
||
Die App bietet mehrere Export-Modi für verschiedene Anwendungsfälle:
|
||
|
||
### PDF-Export 📄
|
||
|
||
**Monats-Export:**
|
||
- Klicke auf "PDF Export" in der Monatsansicht
|
||
- Exportiert alle Einträge des aktuellen Monats
|
||
- Professionelles Layout mit:
|
||
- Mitarbeiter-Informationen (Name, Personal-Nr.)
|
||
- Monatsstatistiken (Soll/Ist/Saldo)
|
||
- Vollständige Tabelle aller Einträge
|
||
- Deutsche Formatierung
|
||
|
||
**Bulk-Export:**
|
||
- Aktiviere Bulk-Modus und wähle Einträge aus
|
||
- Klicke auf "PDF exportieren"
|
||
- Exportiert nur ausgewählte Einträge
|
||
- Gleiche Formatierung wie Monats-Export
|
||
|
||
### CSV-Export 📊
|
||
|
||
Die App bietet zwei CSV-Export-Modi über die Filter-Ansicht:
|
||
|
||
**Export Alle (📥)**
|
||
Exportiert **alle** Einträge im gewählten Zeitraum.
|
||
|
||
**Spalten:**
|
||
```
|
||
Datum;Start;Ende;Pause (min);Netto (h);Arbeitsort;Abweichung (h)
|
||
```
|
||
|
||
**Beispiel:**
|
||
```csv
|
||
2025-10-21;08:00;17:00;30;8,50;Büro;+0,50
|
||
2025-10-22;09:00;18:00;45;8,25;Home;+0,25
|
||
2025-10-23;08:30;16:30;30;7,50;Büro;-0,50
|
||
```
|
||
|
||
**Export Abweichungen (⚠️)**
|
||
Exportiert **nur** Tage mit ≠ 8,0 Stunden.
|
||
|
||
**Zweck:** Gleitzeit-Nachweise für HR (nur relevante Über-/Unterschreitungen)
|
||
|
||
**Beispiel:**
|
||
```csv
|
||
2025-10-21;08:00;18:30;45;9,75;Büro;+1,75
|
||
2025-10-23;09:00;15:30;30;6,00;Home;-2,00
|
||
```
|
||
*(Tage mit exakt 8,0h fehlen)*
|
||
|
||
**Format:** Semikolon-getrennt, Komma-Dezimal, YYYY-MM-DD Datum
|
||
|
||
### Datenbank-Backup 💾
|
||
|
||
**Export:**
|
||
1. Gehe zu Einstellungen
|
||
2. Klicke auf "Datenbank exportieren"
|
||
3. JSON-Datei mit Zeitstempel wird heruntergeladen
|
||
4. Enthält: Alle Einträge + Einstellungen + Version
|
||
|
||
**Import:**
|
||
1. Gehe zu Einstellungen
|
||
2. Klicke auf "Datenbank importieren"
|
||
3. Wähle JSON-Backup-Datei
|
||
4. Bestätige Überschreiben der Daten
|
||
5. Alte Daten werden gelöscht, neue importiert
|
||
|
||
**Verwendung:**
|
||
- Regelmäßige Backups vor Updates
|
||
- Migration zwischen Instanzen/Servern
|
||
- Datensicherung
|
||
|
||
## 📡 API-Endpunkte
|
||
|
||
### Einträge
|
||
- `GET /api/entries?from=YYYY-MM-DD&to=YYYY-MM-DD` - Einträge abrufen
|
||
- `POST /api/entries` - Eintrag erstellen
|
||
- `PUT /api/entries/:id` - Eintrag aktualisieren
|
||
- `DELETE /api/entries/:id` - Eintrag löschen
|
||
|
||
### Einstellungen
|
||
- `GET /api/settings/:key` - Setting abrufen
|
||
- `POST /api/settings` - Setting speichern `{key, value}`
|
||
- `GET /api/settings` - Alle Settings
|
||
|
||
### Datenbank-Management
|
||
- `GET /api/database/export` - Vollständigen DB-Export als JSON
|
||
- `POST /api/database/import` - DB-Import aus JSON
|
||
- `DELETE /api/entries/all` - Alle Einträge löschen (für Import)
|
||
|
||
## 🔄 CI/CD & Deployment
|
||
|
||
Die App verwendet Gitea Actions für automatische Builds und Deployments:
|
||
|
||
**Automatische Docker Builds:**
|
||
- Bei Push zu `main`/`master` Branch
|
||
- Nur bei relevanten Änderungen (Server, Frontend, Dependencies)
|
||
- Ignoriert README, Workflow-Änderungen
|
||
- Erstellt Images mit Tags: `latest` + Commit-SHA
|
||
|
||
**Container Registry:**
|
||
- Gehostet auf Gitea: `gitea.fx-se.de/maggot/timetracker`
|
||
- Authentifizierung via Personal Access Token
|
||
- Automatischer Push nach erfolgreichem Build
|
||
|
||
**Workflow-Konfiguration:**
|
||
```yaml
|
||
# Triggert nur bei:
|
||
- server.js, package.json, Dockerfile
|
||
- db/**, public/**
|
||
- Ignoriert: *.md, .gitea/workflows/**, .gitignore
|
||
```
|
||
|
||
**Siehe:** `.gitea/workflows/docker-build.yml` für Details
|
||
|
||
## 🛠️ Entwicklung
|
||
|
||
**Architektur:** Single-Page Application (SPA) mit REST-API Backend
|
||
|
||
**Tech-Details:**
|
||
- Modulare Frontend-Architektur (5 separate JS-Dateien)
|
||
- Flatpickr für Touch-optimierte Picker (auch in Tabellen-Inline-Edit)
|
||
- Lucide Icons für Symbolik
|
||
- jsPDF + autoTable für PDF-Generierung
|
||
- SQLite für dateibasierte Persistenz
|
||
- Server-seitige Berechnungen für Datenintegrität
|
||
- Responsive Design (Tailwind CSS via CDN)
|
||
|
||
**Datenpersistenz:**
|
||
- SQLite-Datenbank: `db/timetracker.db`
|
||
- Automatische Migrations beim Start
|
||
- Volume-Mounting in Docker für Persistenz
|
||
- JSON-basierte Backups für Migration
|
||
|
||
**Code-Organisation:**
|
||
- `state.js`: Globaler Application State
|
||
- `utils.js`: Hilfsfunktionen (Datum, Zeit, Format)
|
||
- `holidays.js`: Feiertagsberechnung (16 Bundesländer)
|
||
- `api.js`: Backend-Kommunikation
|
||
- `main.js`: Hauptlogik, UI, Event-Handler
|
||
|
||
## 📄 Lizenz
|
||
|
||
MIT License - siehe LICENSE Datei
|
||
|
||
---
|
||
|
||
**Entwickelt mit ❤️ für deutsches Arbeitszeitrecht**
|