feat: add README and change default working hours to 60
This commit is contained in:
parent
e931b97037
commit
b3d4eec456
3 changed files with 775 additions and 2 deletions
773
README.md
Normal file
773
README.md
Normal file
|
|
@ -0,0 +1,773 @@
|
|||
# Zeiterfassungssystem für pädagogische Mitarbeiter
|
||||
|
||||
Eine vollständige Webanwendung zur Erfassung und Verwaltung von Flexistunden für pädagogische Mitarbeiter (PM) an Schulen.
|
||||
|
||||
## 📋 Inhaltsverzeichnis
|
||||
|
||||
- [Überblick](#überblick)
|
||||
- [Funktionen](#funktionen)
|
||||
- [Technologie-Stack](#technologie-stack)
|
||||
- [Voraussetzungen](#voraussetzungen)
|
||||
- [Installation](#installation)
|
||||
- [Konfiguration](#konfiguration)
|
||||
- [Verwendung](#verwendung)
|
||||
- [API-Dokumentation](#api-dokumentation)
|
||||
- [Architektur](#architektur)
|
||||
- [Sicherheit](#sicherheit)
|
||||
- [Backup & Wartung](#backup--wartung)
|
||||
- [Fehlerbehebung](#fehlerbehebung)
|
||||
|
||||
## 🎯 Überblick
|
||||
|
||||
Diese Anwendung wurde entwickelt, um die Erfassung von Flexistunden (zusätzliche Arbeitsstunden) für pädagogische Mitarbeiter an Schulen zu vereinfachen. Sie ermöglicht:
|
||||
|
||||
- **Mitarbeitern**: Wöchentliche Zeiterfassung anhand eines vorkonfigurierten Stundenplans
|
||||
- **Administratoren**: Vollständige Verwaltung von Benutzern, Stundenplänen, Schuljahren und Zeiteinträgen
|
||||
|
||||
Das System arbeitet mit ISO-Kalenderwochen und unterstützt schuljahrbezogene Auswertungen.
|
||||
|
||||
## ✨ Funktionen
|
||||
|
||||
### Für Mitarbeiter
|
||||
|
||||
- **Wochenbasierte Zeiterfassung**: Auswahl der gearbeiteten Zeiten aus dem Stundenplan
|
||||
- **Kalenderwochen-Navigation**: Einfaches Vor- und Zurückblättern zwischen Wochen
|
||||
- **Jahresübersicht**: Anzeige der geleisteten vs. Soll-Arbeitsstunden
|
||||
- **Responsive Design**: Optimiert für Desktop, Tablet und Mobile
|
||||
|
||||
### Für Administratoren
|
||||
|
||||
- **Benutzerverwaltung**:
|
||||
- Benutzer anlegen, bearbeiten und löschen
|
||||
- Jahresarbeitsstunden pro Benutzer festlegen (Standard: 1800h)
|
||||
- Passwörter zurücksetzen
|
||||
- **Stundenplan-Management**:
|
||||
- Wochenstundenplan mit Unterrichts- und Pausenzeiten erstellen
|
||||
- Unterrichtsstunden und Pausen unterscheiden
|
||||
- Zeiten mit Titeln versehen (z.B. "Mathematik", "Pause")
|
||||
|
||||
- **Schuljahrverwaltung**:
|
||||
- Schuljahre mit Start- und Enddatum definieren
|
||||
- Aktives Schuljahr setzen
|
||||
- Jahresberechnungen basierend auf aktivem Schuljahr
|
||||
|
||||
- **Zeiteintrags-Verwaltung**:
|
||||
- Alle Zeiteinträge einsehen und bearbeiten
|
||||
- Manuelle Stundeneintragungen (positiv = Abzug, negativ = Hinzurechnung)
|
||||
- Einzelne Einträge korrigieren oder löschen
|
||||
|
||||
- **Berichtswesen**:
|
||||
- Jahresübersicht aller Mitarbeiter
|
||||
- PDF-Export der Jahresübersicht
|
||||
- Wochenweise Stundenauswertung
|
||||
|
||||
## 🛠 Technologie-Stack
|
||||
|
||||
### Frontend
|
||||
|
||||
- **Elm 0.19**: Funktionale Programmiersprache für type-safe UI
|
||||
- **Bulma CSS**: Modernes CSS-Framework
|
||||
- **Font Awesome**: Icons
|
||||
- **LocalStorage**: Client-seitige Datenpersistenz für Authentifizierung
|
||||
|
||||
### Backend
|
||||
|
||||
- **Go (Golang)**: Performante Backend-Sprache
|
||||
- **Echo Framework**: Web-Framework für Go
|
||||
- **SQLite**: Embedded SQL-Datenbank
|
||||
- **JWT**: Token-basierte Authentifizierung
|
||||
- **bcrypt**: Passwort-Hashing
|
||||
- **gofpdf**: PDF-Generierung
|
||||
|
||||
### Deployment
|
||||
|
||||
- **Docker**: Containerisierung
|
||||
- **Docker Compose**: Orchestrierung
|
||||
|
||||
## 📦 Voraussetzungen
|
||||
|
||||
### Für Docker-Deployment (empfohlen)
|
||||
|
||||
- Docker (Version 20.10+)
|
||||
- Docker Compose (Version 1.29+)
|
||||
|
||||
### Für lokale Entwicklung
|
||||
|
||||
- Go 1.21+
|
||||
- Elm 0.19
|
||||
- Node.js 16+ (für Elm-Tooling)
|
||||
- SQLite3
|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
### Option 1: Docker Compose (Produktion)
|
||||
|
||||
1. **Repository klonen**
|
||||
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd zeiterfassung
|
||||
```
|
||||
|
||||
2. **Umgebungsvariablen konfigurieren**
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
Wichtige Variablen in `.env`:
|
||||
|
||||
```env
|
||||
PORT=8080
|
||||
DB_PATH=/data/timetracking.db
|
||||
JWT_SECRET=ihr-sicheres-geheimnis-hier-ändern
|
||||
TZ=Europe/Berlin
|
||||
```
|
||||
|
||||
3. **Anwendung starten**
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
4. **Anwendung aufrufen**
|
||||
|
||||
```
|
||||
http://localhost:8080
|
||||
```
|
||||
|
||||
**Standard-Anmeldedaten:**
|
||||
|
||||
- Benutzername: `admin`
|
||||
- Passwort: `admin123`
|
||||
|
||||
⚠️ **WICHTIG**: Ändern Sie das Admin-Passwort sofort nach der ersten Anmeldung!
|
||||
|
||||
### Option 2: Lokale Entwicklung
|
||||
|
||||
1. **Backend kompilieren**
|
||||
|
||||
```bash
|
||||
go mod download
|
||||
go build -o timetracking
|
||||
```
|
||||
|
||||
2. **Frontend kompilieren**
|
||||
|
||||
```bash
|
||||
cd static
|
||||
elm make Main.elm --output=elm.js --optimize
|
||||
cd ..
|
||||
```
|
||||
|
||||
3. **Umgebungsvariablen setzen**
|
||||
|
||||
```bash
|
||||
export PORT=8080
|
||||
export DB_PATH=./timetracking.db
|
||||
export JWT_SECRET=development-secret
|
||||
```
|
||||
|
||||
4. **Anwendung starten**
|
||||
|
||||
```bash
|
||||
./timetracking
|
||||
```
|
||||
|
||||
## ⚙️ Konfiguration
|
||||
|
||||
### Umgebungsvariablen
|
||||
|
||||
| Variable | Beschreibung | Standard | Erforderlich |
|
||||
| ------------- | ------------------------------- | ------------------- | ------------ |
|
||||
| `PORT` | HTTP-Server Port | `8080` | Nein |
|
||||
| `DB_PATH` | Pfad zur SQLite-Datenbank | `./timetracking.db` | Nein |
|
||||
| `JWT_SECRET` | Geheimnis für JWT-Token | - | **Ja** |
|
||||
| `TZ` | Zeitzone | `Europe/Berlin` | Nein |
|
||||
| `ENVIRONMENT` | `production` für HTTPS-Redirect | - | Nein |
|
||||
|
||||
### Docker-Volumes
|
||||
|
||||
Das Docker-Setup erstellt ein persistentes Volume für die Datenbank:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
timetracking-data:
|
||||
driver: local
|
||||
```
|
||||
|
||||
Die Datenbank wird unter `/data/timetracking.db` im Container gespeichert.
|
||||
|
||||
## 📖 Verwendung
|
||||
|
||||
### Ersteinrichtung als Administrator
|
||||
|
||||
1. **Anmelden** mit den Standard-Credentials (admin/admin123)
|
||||
|
||||
2. **Admin-Passwort ändern**:
|
||||
- Gehe zu "Benutzer" Tab
|
||||
- Klicke auf "PW Reset" beim Admin-Benutzer
|
||||
- Neues sicheres Passwort eingeben
|
||||
|
||||
3. **Schuljahr erstellen**:
|
||||
- Wechsle zum "Schuljahre" Tab
|
||||
- Erstelle ein Schuljahr (z.B. "2024/2025")
|
||||
- Startdatum: 01.08.2024
|
||||
- Enddatum: 31.07.2025
|
||||
- Klicke auf "Aktivieren"
|
||||
|
||||
4. **Stundenplan erstellen**:
|
||||
- Wechsle zum "Stundenplan" Tab
|
||||
- Füge Unterrichtsstunden hinzu:
|
||||
- Wochentag auswählen
|
||||
- Start- und Endzeit eingeben
|
||||
- Typ: "Unterricht" oder "Pause"
|
||||
- Titel vergeben (z.B. "Mathematik 1a")
|
||||
|
||||
5. **Mitarbeiter anlegen**:
|
||||
- Wechsle zum "Benutzer" Tab
|
||||
- "Benutzer anlegen"
|
||||
- Benutzername und Passwort eingeben
|
||||
- Jahresarbeitsstunden festlegen (Standard: 1800h)
|
||||
- Admin-Rechte nur für weitere Administratoren
|
||||
|
||||
### Zeiterfassung als Mitarbeiter
|
||||
|
||||
1. **Anmelden** mit persönlichen Zugangsdaten
|
||||
|
||||
2. **Wochenansicht**:
|
||||
- Zeigt aktuelle Kalenderwoche mit Datumsbereich
|
||||
- Navigation: "Vorherige Woche" / "Nächste Woche"
|
||||
|
||||
3. **Stunden erfassen**:
|
||||
- Klicke auf die Zeitslots, die du gearbeitet hast
|
||||
- Ausgewählte Zeiten werden grün markiert
|
||||
- Klicke "Speichern" zum Übernehmen
|
||||
|
||||
4. **Woche bearbeiten**:
|
||||
- Falls bereits erfasst, erscheint "Bearbeiten"-Button
|
||||
- Aktiviert Bearbeitungsmodus
|
||||
- "Einträge löschen" entfernt alle Einträge der Woche
|
||||
- Neue Auswahl treffen und "Änderungen speichern"
|
||||
|
||||
5. **Jahresübersicht prüfen**:
|
||||
- Unten auf der Seite: "Jahresgesamtzeit"
|
||||
- Zeigt: Soll-Stunden, Geleistete Stunden, Verbleibende Stunden
|
||||
- Fortschrittsbalken visualisiert den Status
|
||||
|
||||
### Administrative Aufgaben
|
||||
|
||||
#### Manuelle Stundeneintragung
|
||||
|
||||
Für Korrekturen oder Sonderfälle:
|
||||
|
||||
1. Gehe zu "Zeiteinträge" Tab
|
||||
2. Sektion "Manuelle Stundeneintragung"
|
||||
3. Mitarbeiter auswählen
|
||||
4. Datum eingeben
|
||||
5. Stunden eingeben:
|
||||
- **Positive Werte** (z.B. `2.5`): Werden **abgezogen** (z.B. Krankheit, Urlaub)
|
||||
- **Negative Werte** (z.B. `-3.0`): Werden **hinzugerechnet** (z.B. Nachholung, Sondereinsatz)
|
||||
|
||||
#### Zeiteinträge bearbeiten
|
||||
|
||||
1. Gehe zu "Zeiteinträge" Tab
|
||||
2. Liste aller Einträge mit Bearbeitungsmöglichkeit
|
||||
3. "Bearbeiten" klicken:
|
||||
- Datum ändern
|
||||
- Start-/Endzeit anpassen
|
||||
- Typ ändern (Unterricht/Pause/Manuell)
|
||||
4. Speichern oder Löschen
|
||||
|
||||
#### PDF-Export
|
||||
|
||||
1. Gehe zu "Zeiteinträge" Tab
|
||||
2. Sektion "Jahresübersicht"
|
||||
3. Klicke "PDF exportieren"
|
||||
4. PDF enthält:
|
||||
- Schuljahrname und Zeitraum
|
||||
- Alle Mitarbeiter mit Soll/Ist/Differenz
|
||||
- Generierungsdatum
|
||||
|
||||
## 🔌 API-Dokumentation
|
||||
|
||||
### Authentifizierung
|
||||
|
||||
Alle geschützten Endpunkte erfordern einen JWT-Token im Header:
|
||||
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
### Öffentliche Endpunkte
|
||||
|
||||
#### `POST /api/login`
|
||||
|
||||
Benutzer-Anmeldung
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"username": "admin",
|
||||
"password": "admin123"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "eyJhbGc...",
|
||||
"username": "admin",
|
||||
"is_admin": true
|
||||
}
|
||||
```
|
||||
|
||||
### Geschützte Endpunkte (Benutzer)
|
||||
|
||||
#### `GET /api/schedules`
|
||||
|
||||
Alle Stundenpläne abrufen
|
||||
|
||||
#### `GET /api/my-time-entries`
|
||||
|
||||
Eigene Zeiteinträge abrufen
|
||||
|
||||
#### `POST /api/time-entries/batch`
|
||||
|
||||
Mehrere Zeiteinträge auf einmal erstellen
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"schedule_id": 1,
|
||||
"date": "2024-11-04",
|
||||
"type": "lesson",
|
||||
"start_time": "08:00",
|
||||
"end_time": "09:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### `DELETE /api/my-time-entries/week?year=2024&week=45`
|
||||
|
||||
Alle eigenen Einträge einer Woche löschen
|
||||
|
||||
#### `GET /api/week-dates?year=2024&week=45`
|
||||
|
||||
Datumsbereich einer Kalenderwoche abrufen
|
||||
|
||||
#### `GET /api/week-has-entries?year=2024&week=45`
|
||||
|
||||
Prüfen, ob für eine Woche bereits Einträge existieren
|
||||
|
||||
#### `GET /api/yearly-hours-summary`
|
||||
|
||||
Jahresübersicht für alle Benutzer
|
||||
|
||||
#### `GET /api/my-info`
|
||||
|
||||
Eigene Benutzerinformationen abrufen
|
||||
|
||||
#### `GET /api/school-year/active`
|
||||
|
||||
Aktives Schuljahr abrufen
|
||||
|
||||
### Admin-Endpunkte
|
||||
|
||||
#### Stundenplan-Verwaltung
|
||||
|
||||
- `POST /api/admin/schedules` - Stundenplan erstellen
|
||||
- `DELETE /api/admin/schedules/delete?id=1` - Stundenplan löschen
|
||||
|
||||
#### Benutzerverwaltung
|
||||
|
||||
- `POST /api/admin/users` - Benutzer erstellen
|
||||
- `GET /api/admin/users/list` - Alle Benutzer auflisten
|
||||
- `PUT /api/admin/users/:id` - Benutzer bearbeiten (Arbeitsstunden)
|
||||
- `PUT /api/admin/users/:id/reset-password` - Passwort zurücksetzen
|
||||
- `DELETE /api/admin/users/delete?id=2` - Benutzer löschen
|
||||
|
||||
#### Zeiteintrags-Verwaltung
|
||||
|
||||
- `GET /api/admin/time-entries` - Alle Zeiteinträge
|
||||
- `PUT /api/admin/time-entries/:id` - Zeiteintrag bearbeiten
|
||||
- `DELETE /api/admin/time-entries/:id` - Zeiteintrag löschen
|
||||
- `POST /api/admin/time-entry` - Manueller Zeiteintrag
|
||||
|
||||
#### Schuljahrverwaltung
|
||||
|
||||
- `GET /api/admin/school-years` - Alle Schuljahre
|
||||
- `POST /api/admin/school-years` - Schuljahr erstellen
|
||||
- `PUT /api/admin/school-years/:id/activate` - Schuljahr aktivieren
|
||||
- `DELETE /api/admin/school-years/:id` - Schuljahr löschen
|
||||
|
||||
#### Berichte
|
||||
|
||||
- `GET /api/admin/yearly-summary/pdf` - Jahresübersicht als PDF
|
||||
|
||||
## 🏗 Architektur
|
||||
|
||||
### Backend-Struktur
|
||||
|
||||
```
|
||||
.
|
||||
├── main.go # Einstiegspunkt, Server-Setup
|
||||
├── handlers.go # HTTP-Handler für alle Endpunkte
|
||||
├── middleware.go # JWT-Auth, Admin-Check, Rate-Limiting
|
||||
├── database.go # Datenbanklogik und Queries
|
||||
├── models.go # Datenstrukturen
|
||||
├── pdf.go # PDF-Generierung
|
||||
├── docker-compose.yml # Docker-Orchestrierung
|
||||
└── Dockerfile # Container-Image
|
||||
```
|
||||
|
||||
### Frontend-Struktur
|
||||
|
||||
```
|
||||
static/
|
||||
├── Main.elm # Elm-Hauptanwendung
|
||||
│ ├── Model # Anwendungszustand
|
||||
│ ├── Update # Zustandsänderungen
|
||||
│ ├── View # UI-Rendering
|
||||
│ └── Subscriptions # Event-Handling
|
||||
├── index.html # HTML-Wrapper
|
||||
└── elm.js # Kompilierte Elm-Anwendung
|
||||
```
|
||||
|
||||
### Datenbank-Schema
|
||||
|
||||
#### Tabelle: `users`
|
||||
|
||||
```sql
|
||||
id INTEGER PRIMARY KEY
|
||||
username TEXT UNIQUE NOT NULL
|
||||
password TEXT NOT NULL (bcrypt-hashed)
|
||||
is_admin BOOLEAN DEFAULT 0
|
||||
yearly_hours REAL DEFAULT 1800.0
|
||||
created_at DATETIME
|
||||
```
|
||||
|
||||
#### Tabelle: `schedules`
|
||||
|
||||
```sql
|
||||
id INTEGER PRIMARY KEY
|
||||
day_of_week INTEGER (0=Montag, 4=Freitag)
|
||||
start_time TEXT (HH:MM)
|
||||
end_time TEXT (HH:MM)
|
||||
type TEXT (lesson/break)
|
||||
title TEXT
|
||||
created_at DATETIME
|
||||
```
|
||||
|
||||
#### Tabelle: `time_entries`
|
||||
|
||||
```sql
|
||||
id INTEGER PRIMARY KEY
|
||||
user_id INTEGER (FK -> users)
|
||||
schedule_id INTEGER (FK -> schedules)
|
||||
date TEXT (YYYY-MM-DD)
|
||||
type TEXT (lesson/break/manual)
|
||||
start_time TEXT
|
||||
end_time TEXT
|
||||
created_at DATETIME
|
||||
```
|
||||
|
||||
#### Tabelle: `school_years`
|
||||
|
||||
```sql
|
||||
id INTEGER PRIMARY KEY
|
||||
name TEXT UNIQUE
|
||||
start_date DATE
|
||||
end_date DATE
|
||||
is_active BOOLEAN DEFAULT 0
|
||||
created_at DATETIME
|
||||
```
|
||||
|
||||
#### Tabelle: `audit_logs`
|
||||
|
||||
```sql
|
||||
id INTEGER PRIMARY KEY
|
||||
user_id INTEGER
|
||||
action TEXT
|
||||
details TEXT
|
||||
created_at DATETIME
|
||||
```
|
||||
|
||||
### Stundenberechnung
|
||||
|
||||
Die Anwendung berechnet Arbeitsstunden nach folgenden Regeln:
|
||||
|
||||
1. **Unterrichtsstunden** (`type: "lesson"`): **1,0 Stunde** (fest)
|
||||
2. **Pausen** (`type: "break"`): Differenz zwischen End- und Startzeit
|
||||
3. **Manuelle Einträge** (`type: "manual"`):
|
||||
- Positive Werte werden abgezogen
|
||||
- Negative Werte werden hinzugerechnet
|
||||
|
||||
**Beispiel:**
|
||||
|
||||
```
|
||||
Unterricht 08:00-09:00 → 1,0h
|
||||
Pause 09:00-09:15 → 0,25h
|
||||
Manueller Eintrag: 2.5 → -2,5h (Abzug)
|
||||
Manueller Eintrag: -1.0 → +1,0h (Zuschlag)
|
||||
```
|
||||
|
||||
### ISO-Kalenderwochen
|
||||
|
||||
Die Anwendung verwendet ISO 8601 Kalenderwochen:
|
||||
|
||||
- Woche beginnt am Montag
|
||||
- Erste Woche des Jahres enthält den 4. Januar
|
||||
- 52 oder 53 Wochen pro Jahr
|
||||
|
||||
## 🔒 Sicherheit
|
||||
|
||||
### Implementierte Sicherheitsmaßnahmen
|
||||
|
||||
1. **Passwort-Hashing**: bcrypt mit Default-Cost (10 Runden)
|
||||
2. **JWT-Authentifizierung**: HMAC-SHA256 mit 2h Ablaufzeit
|
||||
3. **CORS-Protection**: Konfigurierbare Origins
|
||||
4. **Rate Limiting**: 5 Login-Versuche pro Minute pro IP
|
||||
5. **SQL-Injection-Schutz**: Prepared Statements
|
||||
6. **Admin-Schutz**: Admin-Benutzer (ID=1) kann nicht gelöscht werden
|
||||
7. **Input-Validierung**: Server- und clientseitig
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **JWT_SECRET ändern**: Verwenden Sie einen starken, zufälligen String (64+ Zeichen)
|
||||
|
||||
```bash
|
||||
openssl rand -base64 64
|
||||
```
|
||||
|
||||
2. **HTTPS verwenden**: In Produktion immer TLS/SSL aktivieren
|
||||
|
||||
```env
|
||||
ENVIRONMENT=production
|
||||
```
|
||||
|
||||
3. **Regelmäßige Backups**: Sichern Sie die Datenbank täglich
|
||||
|
||||
4. **Starke Passwörter**: Mindestens 12 Zeichen, Mix aus Groß-/Kleinbuchstaben, Zahlen, Sonderzeichen
|
||||
|
||||
5. **Updates**: Halten Sie Dependencies aktuell
|
||||
```bash
|
||||
go get -u ./...
|
||||
docker-compose pull
|
||||
```
|
||||
|
||||
## 💾 Backup & Wartung
|
||||
|
||||
### Datenbank-Backup
|
||||
|
||||
**Docker-Setup:**
|
||||
|
||||
```bash
|
||||
# Backup erstellen
|
||||
docker exec school-timetracking sqlite3 /data/timetracking.db ".backup '/data/backup-$(date +%Y%m%d).db'"
|
||||
docker cp school-timetracking:/data/backup-$(date +%Y%m%d).db ./backups/
|
||||
|
||||
# Backup wiederherstellen
|
||||
docker cp ./backups/backup-20241108.db school-timetracking:/data/timetracking.db
|
||||
docker-compose restart
|
||||
```
|
||||
|
||||
**Lokales Setup:**
|
||||
|
||||
```bash
|
||||
# Backup
|
||||
sqlite3 timetracking.db ".backup 'backup-$(date +%Y%m%d).db'"
|
||||
|
||||
# Wiederherstellen
|
||||
cp backup-20241108.db timetracking.db
|
||||
```
|
||||
|
||||
### Automatisches Backup (Cron)
|
||||
|
||||
Erstellen Sie ein Backup-Script `backup.sh`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
BACKUP_DIR="/path/to/backups"
|
||||
DATE=$(date +%Y%m%d-%H%M%S)
|
||||
|
||||
docker exec school-timetracking sqlite3 /data/timetracking.db ".backup '/data/backup-$DATE.db'"
|
||||
docker cp school-timetracking:/data/backup-$DATE.db $BACKUP_DIR/
|
||||
|
||||
# Alte Backups löschen (älter als 30 Tage)
|
||||
find $BACKUP_DIR -name "backup-*.db" -mtime +30 -delete
|
||||
```
|
||||
|
||||
Crontab-Eintrag (täglich um 3 Uhr):
|
||||
|
||||
```
|
||||
0 3 * * * /path/to/backup.sh
|
||||
```
|
||||
|
||||
### Log-Rotation
|
||||
|
||||
Docker Compose Log-Größe begrenzen:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
timetracking:
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
```
|
||||
|
||||
### Updates durchführen
|
||||
|
||||
```bash
|
||||
# Repository aktualisieren
|
||||
git pull
|
||||
|
||||
# Neue Images bauen
|
||||
docker-compose build
|
||||
|
||||
# Container neu starten
|
||||
docker-compose down
|
||||
docker-compose up -d
|
||||
|
||||
# Logs prüfen
|
||||
docker-compose logs -f
|
||||
```
|
||||
|
||||
## 🐛 Fehlerbehebung
|
||||
|
||||
### Anwendung startet nicht
|
||||
|
||||
**Problem**: Container startet nicht
|
||||
|
||||
```bash
|
||||
docker-compose logs timetracking
|
||||
```
|
||||
|
||||
**Häufige Ursachen:**
|
||||
|
||||
- `JWT_SECRET` nicht gesetzt → Setzen Sie die Variable in `.env`
|
||||
- Port 8080 bereits belegt → Ändern Sie `PORT` in `.env`
|
||||
- Datenbank-Berechtigungen → Prüfen Sie Volume-Permissions
|
||||
|
||||
### Login funktioniert nicht
|
||||
|
||||
**Problem**: "Invalid credentials" trotz korrekten Passworts
|
||||
|
||||
**Lösung:**
|
||||
|
||||
```bash
|
||||
# Admin-Passwort zurücksetzen
|
||||
docker exec -it school-timetracking /bin/sh
|
||||
sqlite3 /data/timetracking.db
|
||||
|
||||
# In SQLite:
|
||||
UPDATE users SET password = '$2a$10$...' WHERE username = 'admin';
|
||||
.exit
|
||||
```
|
||||
|
||||
Generieren Sie einen neuen bcrypt-Hash:
|
||||
|
||||
```bash
|
||||
# Mit Go
|
||||
echo -n 'neues-passwort' | go run -e 'import "golang.org/x/crypto/bcrypt"; pass, _ := bcrypt.GenerateFromPassword([]byte(os.Args[1]), bcrypt.DefaultCost); fmt.Println(string(pass))'
|
||||
```
|
||||
|
||||
### Zeiteinträge werden nicht gespeichert
|
||||
|
||||
**Problem**: Fehler beim Speichern von Zeiteinträgen
|
||||
|
||||
**Prüfen:**
|
||||
|
||||
1. Browser-Konsole auf JavaScript-Fehler prüfen
|
||||
2. Backend-Logs prüfen: `docker-compose logs -f`
|
||||
3. JWT-Token gültig? → Neu anmelden
|
||||
4. Datenbank-Speicherplatz verfügbar?
|
||||
|
||||
### PDF-Export schlägt fehl
|
||||
|
||||
**Problem**: "Failed to generate PDF"
|
||||
|
||||
**Lösung:**
|
||||
|
||||
```bash
|
||||
# Container-Logs prüfen
|
||||
docker-compose logs timetracking | grep -i pdf
|
||||
|
||||
# Häufig: Fehlende Schriftarten
|
||||
# → Rebuilden Sie das Image
|
||||
docker-compose build --no-cache
|
||||
```
|
||||
|
||||
### Responsive Layout funktioniert nicht
|
||||
|
||||
**Problem**: Mobile Ansicht nicht korrekt
|
||||
|
||||
**Lösung:**
|
||||
|
||||
- Browser-Cache leeren
|
||||
- Elm neu kompilieren:
|
||||
```bash
|
||||
cd static
|
||||
elm make Main.elm --output=elm.js --optimize
|
||||
```
|
||||
|
||||
### Datenbankfehler nach Update
|
||||
|
||||
**Problem**: "Database schema error"
|
||||
|
||||
**Lösung:**
|
||||
|
||||
```bash
|
||||
# Backup erstellen
|
||||
docker cp school-timetracking:/data/timetracking.db ./backup-pre-migration.db
|
||||
|
||||
# Migration manuell durchführen
|
||||
docker exec -it school-timetracking sqlite3 /data/timetracking.db
|
||||
|
||||
# Fehlende Spalten hinzufügen (Beispiel)
|
||||
ALTER TABLE users ADD COLUMN yearly_hours REAL DEFAULT 1800.0;
|
||||
.exit
|
||||
```
|
||||
|
||||
## 📝 Häufig gestellte Fragen (FAQ)
|
||||
|
||||
**Q: Wie ändere ich die Standard-Arbeitsstunden?**
|
||||
A: Als Admin unter "Benutzer" → Benutzer auswählen → "Arbeitszeit" klicken → Neue Stundenzahl eingeben.
|
||||
|
||||
**Q: Können Mitarbeiter vergangene Wochen bearbeiten?**
|
||||
A: Ja, über die Wochen-Navigation können alle Wochen bearbeitet werden (sofern im aktuellen Schuljahr).
|
||||
|
||||
**Q: Wie funktioniert die Schuljahr-Berechnung?**
|
||||
A: Das System berechnet Stunden nur für Einträge innerhalb des aktiven Schuljahres (Start- bis Enddatum).
|
||||
|
||||
**Q: Was passiert bei 53-Wochen-Jahren?**
|
||||
A: Das System unterstützt ISO-Kalenderwochen inklusive Woche 53 automatisch.
|
||||
|
||||
**Q: Kann ich mehrere Schuljahre parallel nutzen?**
|
||||
A: Es kann immer nur ein Schuljahr aktiv sein. Berechnungen basieren auf diesem Zeitraum.
|
||||
|
||||
**Q: Wie funktionieren negative Stunden?**
|
||||
A: Negative Werte bei manuellen Einträgen werden **zum** Stundenkonto **hinzugerechnet** (für Zusatzleistungen).
|
||||
|
||||
## 📄 Lizenz
|
||||
|
||||
Todo
|
||||
|
||||
## 👥 Kontakt & Support
|
||||
|
||||
Todo
|
||||
|
||||
---
|
||||
|
||||
**Version**: 1.0.0
|
||||
**Letztes Update**: November 2024
|
||||
**Entwickelt für**: Schulen zur Verwaltung von Flexistunden pädagogischer Mitarbeiter
|
||||
Loading…
Add table
Add a link
Reference in a new issue