schakal00783andClaude Opus 5 be37d89d53 feat(projekte): Listenansicht der Projektuebersicht
Umschalter Karten/Liste neben dem Statusfilter, die Wahl merkt sich der
Browser. Die Liste zeigt alle gefilterten Projekte flach ueber die Kunden
hinweg und sortierbar: Projekt mit Code, Toepfen und Tasks, Kunde, Typ,
gebuchte Stunden und Tage, Budget mit freiem Rest, Verbrauchsbalken,
offener Betrag mit erbrachtem Umsatz und das Team. Beträge nur ab
Vorgesetztem.

Ein Klick auf eine Zeile oeffnet dieselbe Detailansicht wie eine Kachel,
in der Liste unterhalb der Tabelle. Dafuer ist der Detailblock einmal
aufgebaut und wird in beiden Ansichten verwendet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 11:28:42 +02:00

perinco Pulse

Zeiterfassung für perinco – live unter https://pulse.perinco.de. Quellcode: git.perinco.de/Sascha/perinco-Pulse. Stil, Themes und Aufbau folgen dem perinco CRM (git.perinco.de/Sascha/perinco-CRM).

Teil Technik Wo
Frontend React 19, TypeScript, Tailwind 4, Vite /var/www/pulse/dist
Backend Express 4, mysql2, exceljs, pdfkit /var/www/pulse/server, 127.0.0.1:5010, Dienst perinco-pulse-backend (User pulse)
Datenbank MariaDB 11.8 perinco_pulse (User pulse)
Webserver Apache Vhost pulse.perinco.de, Let's Encrypt /etc/apache2/sites-available/pulse.perinco.de*.conf

Erster Login: Benutzer admin, Passwort aus ADMIN_PASSWORD in server/.env (wird beim ersten Start einmalig angelegt) – danach unter Mein Konto (unten links auf den Namen klicken) ändern.

Rollen und Menü

Rolle Startseite Menü
Mitarbeiter (user) Buchung Buchung, Projekte (nur zugewiesene, ohne Beträge)
Vorgesetzter (lead) Buchung Dashboard (nur eigenes Team, rekursiv), Buchung, Projekte, Team, Kunden, Reports
Management Dashboard wie Vorgesetzter, sieht alles; Einstellungen nur „SSO-Verwaltung“
Administrator Einstellungen Dashboard, Projekte, Team, Kunden, Reports, Einstellungen – keine Buchung, taucht in Auswertungen nicht auf

Die Startseite gilt nach jeder Anmeldung (Passwort und SSO), auch wenn noch eine alte Seite in der Adresse steht; Neuladen bleibt auf der aktuellen Seite. Das Logo oben links führt ebenfalls zur Startseite.

Rechte werden im Menü und im Backend (403) geprüft. Jeder bucht nur auf Projekte, denen er zugewiesen ist.

Fachregeln

  • Zeiteingabe: 1:23 = 1 h 23 min, 1,5 / 1.5 = 1 h 30 min, außerdem 2, :45, 1h 30m.
  • Projektcode automatisch nach Muster (Standard {KUERZEL}-{JAHR}-{NR} → KUKA-2026-001), Anzeigename nach Muster (Standard {KUNDE} - {PROJEKT} → KUKA - PMO). Beides in Einstellungen → Allgemein.
  • Projekttypen:
    • Billable – Preis pro Stunde oder Tag, Volumen und Laufzeit im Budgettopf.
    • Abruf – Abrechnung nach Aufwand: kein Budgettopf, kein Limit, nur ein Stunden- oder Tagessatz am Projekt (pulse_projects.rate). Gebucht wird innerhalb der Projektlaufzeit, der Umsatz sind abrechenbare Stunden × Satz.
    • Non-billable – intern.
    • Festpreis – fixes Budget, virtueller Stundensatz = Festpreis ÷ gebuchte Stunden (nur intern).
  • Budgettöpfe (mind. einer je Projekt, beliebig viele): Bezeichnung, Laufzeit von/bis, Budget € + Satz (→ Volumen in Stunden/Tagen) oder direktes Kontingent.
    • Gebucht wird nur auf einen Topf, dessen Laufzeit das Leistungsdatum enthält; überlappen Töpfe, zuerst der früher endende.
    • Volumen erreicht oder Ablaufdatum überschritten → Warnung und nicht mehr buchbar.
    • Bei Billable-Projekten verbrauchen nur abrechenbare Stunden das Volumen (Reisezeit o. ä. nicht); ist ein Topf leer, ist er für alles gesperrt.
    • Warnung ab 80 % Verbrauch bzw. 14 Tage vor Ablauf (einstellbar) – im Buchungsdialog, in der Buchungsansicht und an der Projektkarte.
    • Wird ein Topf geändert, ordnet Pulse vorhandene Buchungen neu zu.
  • Umsatz erbracht/offen je Topf: Billable = abrechenbare Stunden × Satz; Festpreis = anteilig nach Kontingent (sonst nach Laufzeit), abgelaufen = voll; offen = Rest in nicht abgelaufenen Töpfen.
  • Soll/Auslastung: Wochenstunden (Standard 40, je Benutzer überschreibbar) ÷ 5 × Arbeitstage bis heute.
  • Löschen: Benutzer, Projekte, Kunden mit Buchungen werden nicht gelöscht, sondern deaktiviert/archiviert – Reports bleiben stimmig. SSO-Benutzer werden nur deaktiviert.

Exporte

Serverseitig erzeugt, alle mit Kopf/Fuß aus Einstellungen → Export (Logo, Akzentfarbe, Titel, 3 Fußspalten, Unterschriftenfelder):

  • Stundennachweis je Monat (PDF, Excel mit Summenformeln, CSV mit UTF-8-BOM/Semikolon): eigener Nachweis, eines Teammitglieds oder aller; filterbar nach Kunde/Projekt; optional mit Sätzen und Beträgen für die Rechnung.
  • Zeitreport nach Kunden/Projekten/Tasks/Mitarbeitern oder als Detailliste.

Listenansichten

src/components/booking/EntryList.tsx zeigt einzelne Buchungen als sortierbare Tabelle: Datum, optional Mitarbeiter, Kunde, Projekt (mit Code), Task (mit Notiz) sowie die Zeit getrennt nach Billable und Non-billable, unten die Summen. Dieselbe Komponente wird an drei Stellen benutzt:

  • Buchung: Umschalter Kalender / Liste neben Woche / Monat / Jahr; die Liste zeigt den jeweils gewählten Zeitraum. Ein Klick auf eine Zeile öffnet die Buchung zum Bearbeiten (nicht in der fremden Teamansicht). Die Wahl merkt sich der Browser.
  • Reports → Zeitreport → Mitarbeiter: Klick auf eine Zeile öffnet die Buchungen dieses Mitarbeiters im Reportzeitraum; ein gesetzter Kundenfilter wird übernommen (GET /api/entries?...&customer_id=).
  • Kunden: Umschalter Karten / Liste mit Ort, Projektanzahl, Stunden, Umsatz erbracht/offen und Team.

src/components/projects/ProjectTable.tsx ist die Listenansicht der Projekte (Umschalter Karten / Liste): flach über alle Kunden statt nach Kunde gruppiert, sortierbar nach Projekt, Kunde, Typ, gebuchten Stunden, Budget, Verbrauch und offenem Betrag. Ein Klick auf eine Zeile öffnet dieselbe Detailansicht wie eine Kachel, hier unterhalb der Tabelle. Beträge sieht nur, wer mindestens Vorgesetzter ist.

SSO / Active Directory

Einrichtung (nur Administrator, Einstellungen → SSO / Entra ID): Microsoft Entra ID per OpenID Connect (Authorization Code, Client Secret AES-verschlüsselt in der DB). App-Registrierung mit Redirect-URI https://pulse.perinco.de/api/auth/sso/callback, delegiert openid profile email, Anwendung User.Read.All mit Administratorzustimmung.

SSO-Verwaltung (Management und Administrator, Einstellungen → SSO-Verwaltung):

  • Links alle zulässigen AD-Konten, rechts die Rollen Mitarbeiter / Vorgesetzter / Management. Konto auf eine Rolle ziehen = nach Pulse übernehmen bzw. Rolle ändern. Alternativ Mehrfachauswahl + Knopf (Handy, Tastatur). Optional gleich einen Vorgesetzten setzen.
  • Zulässig sind nur Konten mit Mail vorname.nachname@perinco.de oder vorname.nachname@icon-experts.de (Bindestriche im Namen erlaubt). Ignoriert werden Adressen mit weiteren Teilen (adm.sascha.wolf@…), Funktionsadressen (info@…), deaktivierte Konten und Konten ohne Lizenz (freigegebene Postfächer) sowie Gäste. Regel: server/src/lib/sso.js → isEligible, Tests: cd server && npm test.
  • Existiert schon ein lokales Konto mit derselben Mail, wird es verknüpft statt doppelt angelegt.
  • Anmelden per Microsoft kann sich nur, wer übernommen wurde. Rollen kommen ausschließlich aus Pulse, AD-Gruppen spielen keine Rolle. Administratoren können hier nicht geändert und nicht vergeben werden.
  • Abgleich: aktualisiert Name, Mail und Jobtitel der übernommenen Konten; wer im AD gelöscht, deaktiviert oder nicht mehr zulässig ist, wird in Pulse deaktiviert. Legt nie selbst Konten an. Die AD-Liste wird 5 Minuten zwischengespeichert („Neu laden“ holt sofort).
  • Externe Benutzer bleiben lokale Konten.

Themes

Sieben Farbwelten, jede in hell und dunkel, gespeichert am Benutzer (pulse_users.theme, theme_mode) und vor dem ersten Bild gesetzt (Inline-Skript in index.html). Sie kommen 1:1 aus dem perinco CRM; drei bringen Bewegung mit:

Theme Bewegung Wo
Rainy Nieselregen mit Aufprall, Wetterleuchten in den Wolken der Kopfleiste src/components/layout/RainyWeather.tsx, .rainy-flash
Snow Schneefall, der sich unten zu einer Decke sammelt; alle 4 Minuten fährt ein Räumfahrzeug durch src/components/layout/SnowWeather.tsx
Aura hell: Sonnenstrahlen, dunkel: Mond mit Sternen; ziehende Wolken und schaukelnde Hügel in der Seitenleiste (@keyframes aura-hills, nur hell) src/components/layout/AuraSky.tsx, src/index.css

Die Animationen hängen am ThemeProvider, liegen über der Oberfläche, fangen keine Klicks ab und bleiben unter Dialogen. Bei „Bewegung reduzieren“ im Betriebssystem bleiben sie alle aus.

Ein neues Theme braucht vier Stellen: Farbblock in src/index.css, Eintrag in THEME_PALETTES samt Beschriftung (src/types.ts), die Freigabeliste im Inline-Skript von index.html und die Prüfung in server/src/routes/auth.js (PATCH /api/auth/me) – fehlt die letzte, lässt sich die Wahl nicht speichern.

Entwicklung

npm install && (cd server && npm install)
cp server/.env.example server/.env   # Werte setzen
# DB z. B. per Tunnel: plink -L 3307:127.0.0.1:3306 root@31.70.144.60  (DB_PORT=3307, DB_NAME=perinco_pulse_dev)
(cd server && npm run dev)           # Backend :5010
npm run dev                          # Frontend :3110, proxyt /api

perinco_pulse_dev enthält Demodaten (Kunden, Projekte, ~1000 Buchungen, Testbenutzer mit Passwort Test12345!) und wird von der Produktion nicht benutzt.

Deployment

$env:PULSE_SSH_PASSWORD = '…'
powershell -File deploy/deploy.ps1          # baut, lädt hoch, tauscht dist atomar, startet Dienst neu
powershell -File deploy/deploy.ps1 -Deps    # zusätzlich npm ci im Backend

Die Produktions-.env liegt nur auf dem Server (/var/www/pulse/server/.env, 600). SETTINGS_KEY nicht ändern, sonst ist das gespeicherte SSO-Secret unlesbar.

Anforderungs-Checkliste

Aus Auftrag und Call-Mitschrift.

Anforderung Status Wo
Dashboard Mgmt/Admin: Billable/Non-billable-Grafik, umschaltbar Tag/Woche/Monat/Quartal/Jahr, animiert ✅ Dashboard
Letzte Buchungen ✅ Dashboard
Mitarbeiter-Übersicht auf-/absteigend, letzte Tage/Woche/Monat/Quartal/Jahr, Filter billable/non-billable ✅ animierte Umsortierung Dashboard
Vorgesetzte sehen nur ihr Team ✅ rekursiv, auch im Backend Dashboard, Reports, Buchung (Teamansicht, nur lesen)
Buchung: Wochenansicht Standard, umschaltbar Monat/Jahr ✅ Buchung
Buchung: zusätzliche Listenansicht (Kunde, Projekt, Task, Billable/Non-billable Zeit) für Woche/Monat/Jahr ✅ Buchung → Kalender/Liste
Klick auf einen Mitarbeiter im Zeitreport zeigt dessen Buchungen des Zeitraums als Liste ✅ Reports → Zeitreport → Mitarbeiter
Kunden: zusätzliche Listenansicht ✅ Kunden → Karten/Liste
Projekte: zusätzliche Listenansicht ✅ Projekte → Karten/Liste
Grünes Plus → Projekt, Task, optionaler Freitext, Zeit rechts daneben, 0:00, 1:23 und 1,5 ✅ Buchungsdialog
Nur zugewiesene Projekte, Task optional ✅ Buchungsdialog
Zeiten bearbeiten und löschen ✅ Klick auf Buchung
Monatsexport Excel/PDF/CSV als Kundenvorlage mit Logo und Footer ✅ (Footer-Inhalt siehe Hinweis) Buchung → Export
Menü je Rolle (Dashboard/Buchung, Projekte, Team, Kunden, Reports, Einstellungen) ✅ Seitenleiste / mobile Leiste
Projekte: User nur zugewiesene; andere alle inkl. Töpfe, bearbeiten/anlegen/entfernen ✅ Projekte
Projekt wählen → Tasks darunter ✅ Projekte
Projektanlage: Name, Code automatisch, Start/Ende, Budget, Tags, Notizen, Typ billable/Abruf/non-billable/Festpreis, Stunde/Tag ✅ Neues Projekt
Budgettopf: Laufzeit, Budget €, Stundensatz, Bezeichnung; n Töpfe; Balken Stunden/Tage/Budget ✅ Projekte
Hinweis beim Buchen, wann Budget endet und wieviel offen ist ✅ Buchungsdialog, Buchung
Topf voll oder abgelaufen → nicht buchbar ✅ serverseitig erzwungen
Nur auf Topf buchen, dessen Laufzeit die Leistung enthält ✅
Töpfe bearbeiten ab Vorgesetzter ✅ Projekte
Festpreis: virtueller Stundensatz intern ✅ Projekt, Projektreport
Report: Gesamt aller Töpfe und einzelne Töpfe ✅ Projektreport → Budgettöpfe
Projekte Usern zuweisen ✅ Projekt → Zuweisen / Formular
Kunden über Projekten ✅ Kunden, Projektformular (+ Kunde)
Team: Hierarchie Vorgesetzte/Mitarbeiter, lokale User anlegen/bearbeiten/löschen, Externe ✅ Organigramm + Liste Team
Kunden anlegen/bearbeiten, wer hat welche Projekte mit welchen Mitarbeitern, Umsatz erbracht/offen, animiert ✅ Kunden
Reports wie Harvest (Report.png), interaktiv, Export Excel/PDF/CSV ✅ Reports → Zeitreport
Report für einzelne Kunden / Projekt wie Report-Kunde.png ✅ Reports → Kunden-/Projektreport
Einstellungen (nur Admin): SSO-Credentials, Userverwaltung, Kopf/Fuß der Exporte ✅ inkl. PDF-/Excel-Vorschau Einstellungen
Arbeitsstunden pro Woche (40) ✅ Einstellungen → Allgemein
Projektbezeichnungen nach Muster ✅ Einstellungen → Allgemein
Themes wie CRM (perinco, Pixel Art, Outdoor, Cyberpunk, Rainy, Snow, Aura – jeweils hell/dunkel, am Benutzer gespeichert) ✅ Kopfleiste
Lokaler Admin mit vorgegebenem Passwort, später änderbar ✅ Mein Konto
Mobil: eigene Ansicht bei Handy ✅ untere Navigation, Tagesstreifen, Bottom-Sheets, schwebender Plus-Knopf
SSO, anfangs normaler Login; AD-User auslesen, Rollen intern ✅ vorbereitet, noch nicht gegen echten Tenant getestet Einstellungen → SSO

Offene Punkte

  • Wordvorlage lag nicht im Ordner. Kopf nutzt das perinco-Logo; die Fußzeilen (Adresse, Registergericht, Bank) bitte in Einstellungen → Export eintragen.
  • SSO ist implementiert, braucht aber eine App-Registrierung in Entra ID zum Test.
  • Nicht umgesetzt, weil nicht gefordert: Rechnungsmodul („Uninvoiced amount“ aus Harvest), gespeicherte Reports.
S
Description
perinco Pulse - Zeiterfassung (pulse.perinco.de)
Readme
2.4 MiB
Languages
TypeScript 63.3%
JavaScript 30.6%
CSS 5.4%
HTML 0.4%
PowerShell 0.3%