Overtime Report Generator

ArbZG-konforme Arbeitszeitnachweise aus Solidtime

View the Project on GitHub icepaule/IceTimereport

Benutzerhandbuch

Inhaltsverzeichnis

  1. Überblick
  2. Konfiguration
  3. Befehle
  4. Excel-Berichte
  5. Automatisierung
  6. FAQ

Detaillierte Erklärung aller Formeln und Algorithmen: Berechnungslogik


Überblick

Der Overtime Report Generator liest deine Zeiterfassung aus Solidtime und erstellt zwei Excel-Arbeitszeitnachweise:

Wie funktioniert die Korrektur?

Die Büro-Version verschiebt Stunden so, dass keine ArbZG-Verstöße mehr sichtbar sind:

Problem Korrektur
Sonntags-/Feiertagsarbeit Stunden → nächster Werktag
Mehr als 10h an einem Tag Überschuss → nächster Werktag
Fehlende Pausen Fiktive Pausenzeiten eingefügt

Wichtig: Die Gesamtstundenzahl bleibt gleich! Es wird nichts gelöscht, nur die Verteilung über die Tage geändert.


Konfiguration

Alle Einstellungen stehen in der Datei .env. Kopiere .env.example und passe die Werte an:

cp .env.example .env
nano .env

Pflichtfelder

Variable Beschreibung Beispiel
DB_HOST Solidtime DB Hostname/Container solidtime-database-1
DB_PORT PostgreSQL Port 5432
DB_NAME Datenbankname solidtime
DB_USER DB Benutzer solidtime
DB_PASS DB Passwort solidtime
MEMBER_ID Deine Member-UUID aus Solidtime 820cff5d-...
EMPLOYEE_NAME Dein Name (für Excel-Header) Max Mustermann
HOURS_PER_WEEK Vertragliche Wochenstunden 39
STATE Bundesland (für Feiertage) BY

Member-ID herausfinden

docker exec solidtime-database-1 psql -U solidtime -d solidtime \
  -c "SELECT m.id, u.name, u.email FROM members m JOIN users u ON m.user_id = u.id"

Client-IDs herausfinden (optional)

Standardmäßig werden alle Zeiteinträge des Members ausgewertet (Multi-Client). Über Umgebungsvariablen können bestimmte Clients ausgeschlossen werden:

docker exec solidtime-database-1 psql -U solidtime -d solidtime \
  -c "SELECT id, name FROM clients"

Siehe Administratorhandbuch für Details zu den Ausschlussregeln.

Optionale Felder

Variable Beschreibung Standard
EXCLUDE_CLIENTS Client-IDs ausschließen (komma-getrennt) (leer = keine Ausschlüsse)
THW_CLIENT_ID Ehrenamt-Client: Wochenend-Einträge ausschließen (leer)
EMPLOYEE_ROLE Funktion/Rolle (leer)
VACATION_DAYS Urlaubstage pro Jahr 30
START_DATE Beginn der Erfassung (Vertragsstart) 2024-01-01
SMTP_* E-Mail-Konfiguration (siehe ADMIN.md)
RCLONE_* Google Drive Sync (siehe ADMIN.md)

Bundesländer

Kürzel Land Kürzel Land
BW Baden-Württemberg NI Niedersachsen
BY Bayern NW Nordrhein-Westfalen
BE Berlin RP Rheinland-Pfalz
BB Brandenburg SL Saarland
HB Bremen SN Sachsen
HH Hamburg ST Sachsen-Anhalt
HE Hessen SH Schleswig-Holstein
MV Mecklenburg-Vorpommern TH Thüringen

Befehle

Alle Befehle werden im Container ausgeführt:

docker exec overtime-report python3 /app/main.py <befehl> [optionen]

generate - Berichte erstellen

Erzeugt beide Excel-Dateien (real + office). Ohne --year werden alle Jahre seit START_DATE generiert, mit kumulativem Überstundenübertrag:

# Alle Jahre seit START_DATE (empfohlen)
docker exec overtime-report python3 /app/main.py generate

# Bestimmtes Jahr (Vorjahre werden für Übertrag berechnet)
docker exec overtime-report python3 /app/main.py generate --year 2025

Ausgabe:

Generating reports for 2024 (State: BY)...
  Checking ArbZG compliance...
  5 days with violations (7 total violations)
  Generating real report...
  -> /output/real/Arbeitszeitnachweis_2024_real.xlsx
  ...
  Year overtime: +42.50h | Cumulative: +42.50h

Generating reports for 2025 (State: BY)...
  Carry-over from prior years: +42.50h
  Vacation carryover from previous year: 3 days
  Checking ArbZG compliance...
  12 days with violations (15 total violations)
  ...
  Year overtime: -12.30h | Cumulative: +30.20h

Done.

Die Dateien liegen danach unter:

check - ArbZG-Compliance prüfen

Zeigt alle ArbZG-Verstöße ohne Excel zu generieren:

docker exec overtime-report python3 /app/main.py check --year 2025

Ausgabe:

ArbZG Check for 2025 (Marcus Pauli):
============================================================
  26.04.2025 (11.1h): §3 >10h (11.1h)
  25.06.2025 (23.3h): §3 >10h (23.3h), §5 Ruhezeit (3.2h < 11h)
  ...

Summary (12 days with violations):
  §3 >10h: 8x
  §4 Pause: 3x
  §5 Ruhezeit: 2x
  §9 Sonntag: 2x

send-email - Monats-E-Mail senden

Sendet den Arbeitszeitnachweis per E-Mail:

# Vormonat automatisch
docker exec overtime-report python3 /app/main.py send-email

# Bestimmter Monat
docker exec overtime-report python3 /app/main.py send-email --year 2025 --month 6

# Test-Mail (an sich selbst)
docker exec overtime-report python3 /app/main.py send-email --test

Excel-Berichte

Reale Version (Arbeitszeitnachweis_YYYY_real.xlsx)

Ein Sheet pro Monat + Zusammenfassungs-Sheet.

Monats-Sheet:

Reale Version — Monatsansicht mit Projekten und ArbZG-Spalte

Spalte Inhalt
Datum TT.MM.JJJJ
Tag Mo, Di, Mi, …
Typ Arbeit, Urlaub, Krank, Gleittag, Feiertag, Samstag, Sonntag
Projekt Solidtime-Projektname(n)
Beschreibung Solidtime-Beschreibung(en)
Ist (h) Tatsächliche Stunden
Soll (h) Vertragliche Stunden (nur bis Stichtag)
ArbZG OK / §3 >10h / §4 Pause / §5 Ruhezeit / §9 Sonntag

Farbcodierung:

Zusammenfassung mit ArbZG-Verstößen:

Reale Version — Zusammenfassung

Büro-Version (Arbeitszeitnachweis_YYYY.xlsx)

Ein Sheet pro Monat + Zusammenfassungs-Sheet mit Urlaubskonto.

Monats-Sheet:

Büro-Version — Monatsansicht mit fiktiven Zeiten

Spalte Inhalt
Datum TT.MM.JJJJ
Tag Mo, Di, Mi, …
Typ Arbeit, Urlaub, Krank, Gleittag, Feiertag, Samstag, Sonntag
Beginn Fiktive Startzeit (08:00)
Ende Berechnete Endzeit
Pause (min) 0/30/45 je nach Stunden
Ist (h) Korrigierte Stunden (max 10h)
Soll (h) Vertragliche Stunden (nur bis Stichtag)

Keine Projektnamen oder Beschreibungen in dieser Version.

Zusammenfassungs-Sheet

Beide Versionen enthalten ein Zusammenfassungs-Sheet:

Büro-Version — Zusammenfassung mit Überstundenkonto und Urlaubsübertrag

Inhalte:


Automatisierung

Der Container führt automatisch folgende Cron-Jobs aus:

Zeitpunkt Aktion
Täglich 06:00 Berichte generieren
Täglich 06:05 Büro-Version zu Google Drive synchronisieren
1. jedes Monats 07:00 Monats-E-Mail senden

Logs prüfen

docker exec overtime-report cat /var/log/overtime-report.log

Cron anpassen

Bearbeite die Datei crontab und baue den Container neu:

nano crontab
docker compose up -d --build

FAQ

Warum unterscheiden sich die Monatssummen zwischen real und Büro?

Die Jahressumme ist identisch. Monatlich kann es Abweichungen geben, weil Wochenend-/Feiertagsstunden auf den nächsten Werktag verschoben werden - auch über Monatsgrenzen hinweg.

Was passiert mit Urlaubs-/Krankheitstagen?

Das Tool erkennt automatisch Solidtime-Projekte mit den Namen “Urlaub”, “Krank” oder “Gleittag” und markiert die Tage entsprechend. Für diese Tage gilt: Ist = Soll = hours_per_day (z.B. 7,8h bei einer 39h-Woche). Damit haben Krankheits- und Urlaubstage keinen Einfluss auf das Überstundenkonto — sie werden als bezahlte Abwesenheit (Entgeltfortzahlung) behandelt.

In der Büro-Version werden dafür fiktive Arbeitszeiten generiert (z.B. 08:00–15:48 bei 7,8h).

Siehe Berechnungslogik für Details und Beispielrechnungen.

Kann ich mehrere Jahre generieren?

Ja. Ohne --year generiert das Tool automatisch alle Jahre seit START_DATE mit kumulativem Überstundenübertrag:

docker exec overtime-report python3 /app/main.py generate

Jedes Jahr erhält den korrekten Übertrag aus den Vorjahren. Die Berichte werden in der Reihenfolge START_DATE.year bis zum aktuellen Jahr erstellt.

Ich arbeite für mehrere Kunden/Arbeitgeber — wie werden die Stunden gezählt?

Standardmäßig werden alle Zeiteinträge über alle Solidtime-Clients hinweg gezählt. Das bedeutet: Arbeit für den Hauptarbeitgeber, Nebentätigkeiten bei anderen Kunden (z.B. HDBW) und Freistellungen (z.B. THW an Werktagen) fließen alle in das Überstundenkonto ein.

Mit EXCLUDE_CLIENTS kannst du bestimmte Clients komplett ausschließen (z.B. private Projekte). Mit THW_CLIENT_ID kannst du ehrenamtliche Wochenendarbeit ausschließen, während Werktags-Einträge als Freistellung zählen.

Siehe Berechnungslogik für Details.

Was bedeutet “Übertrag Vorjahre” im Zusammenfassungs-Sheet?

Das ist die Summe aller Überstunden aus den Jahren vor dem aktuellen Berichtsjahr (seit START_DATE). Zusammen mit den Überstunden des aktuellen Jahres ergibt sich das Gesamtkonto. So geht nichts verloren, wenn ein neues Jahr beginnt.

Warum zeigt das aktuelle Jahr weniger Soll-Stunden als erwartet?

Das aktuelle Jahr wird nur bis zum heutigen Tag berechnet (Stichtag). Zukünftige Tage haben Soll = 0, damit keine falschen Minusstunden entstehen. Das Stichtag-Datum steht als “Stand: TT.MM.JJJJ” im Zusammenfassungs-Sheet.

Was bedeutet “X Tage aus Vorjahr” beim Urlaubskonto?

Wenn eine Urlaubsperiode im Dezember beginnt und im Januar fortgesetzt wird, zählen die Januar-Tage gegen den Urlaubsanspruch des Vorjahres — nicht des neuen Jahres. So wird der Resturlaub korrekt berechnet.

Beispiel: Urlaub vom 31.12.2025 bis 05.01.2026 → Die 2 Werktage im Januar 2026 (2. und 5. Jan) zählen als Urlaub 2025. Das 2026er Urlaubskonto bleibt bei 30 Tagen.

Der Container findet die Solidtime-Datenbank nicht?

Beide Container müssen im selben Docker-Netzwerk sein. Prüfe:

docker network inspect solidtime_internal

Siehe Administratorhandbuch für Details.

Wie genau sind die Pausenzeiten in der Büro-Version?

Die Pausenzeiten sind fiktiv und werden nach ArbZG-Mindestvorgaben berechnet:

Die reale Version prüft deine tatsächlichen Pausen (Lücken zwischen Solidtime-Einträgen). Wenn du pro Tag nur einen durchgehenden Eintrag buchst, wird keine Pausenprüfung durchgeführt — denn ohne Lücken zwischen Einträgen ist eine Messung nicht möglich.