Führt Login mit vier Rollen (Admin, Teamleiter, Mitarbeiter, Beobachter) ein, über die Teammitglieder eigenen Urlaub inkl. Pflicht-Vertreter eintragen können. Die Auslastungsberechnung berücksichtigt Urlaub jetzt als reduzierte Kapazität. Neue Konten vergeben ihr Passwort selbst beim ersten Login. Migrationsskript für bestehende Mitarbeiter aus der Vorversion inklusive. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
7.7 KiB
Ressourcenplanung
Leichtgewichtige App zur Planung von Projekten, Aufgaben, Mitarbeitern, Teams und Urlaub – mit Zeitplan (Gantt), Auslastungs-Heatmap, Team-Verwaltung und Login mit Rollen/Rechten. Daten liegen in SQLite.
Breaking Change: Seit Einführung der Benutzerverwaltung erfordert jeder
API-Zugriff eine angemeldete Sitzung (/health bleibt für den Docker-Healthcheck
offen).
Rollen & Rechte
| Rolle | Rechte |
|---|---|
| Admin | lesend + schreibend auf alles, inkl. Benutzerverwaltung |
| Teamleiter | schreibend auf Mitarbeiter/Teams/Projekte/Aufgaben und eigenen Urlaub; lesend auf Urlaub anderer |
| Mitarbeiter | schreibend nur auf eigenen Urlaub (mit Vertreterpflicht) und den Status eigener zugewiesener Aufgaben; sonst lesend |
| Beobachter | nur lesend, sieht ausschließlich Zeitplan/Auslastung/Urlaub |
Passwort-Vergabe: Neue Benutzerkonten (auch der Start-Admin) werden ohne Passwort angelegt. Beim allerersten Login wird das eingegebene Passwort als neues Passwort übernommen.
Urlaubsvertretung: Jeder Urlaubseintrag benötigt einen Vertreter aus der Mitarbeiterliste. Eine Person darf nicht gleichzeitig (überlappender Zeitraum) als Vertreter für zwei Urlaube innerhalb derselben Berechtigungsrolle der jeweils antragstellenden Person eingetragen sein.
Aufbau
ressourcenplanung/
├── server/ Node/Express + SQLite (better-sqlite3)
│ ├── schema.sql Tabellen & Beziehungen (inkl. users, sessions, vacations)
│ ├── db.js DB-Init, Beispieldaten, Start-Admin-Bootstrap
│ ├── auth.js Passwort-Hashing, Sessions, requireAuth/requireRole
│ ├── index.js REST-API (CRUD + Auslastungsberechnung)
│ └── scripts/
│ ├── reset-admin.js Admin-Zugang anlegen/zurücksetzen (CLI)
│ └── migrate-team-accounts.js Login-Konten für bestehende Mitarbeiter anlegen (CLI)
└── client/ Vue 3 + Vite
└── src/
├── App.vue Login-Gate + rollenbasierte Tab-Navigation
├── LoginPanel.vue Login (Erstanmeldung vergibt Passwort)
├── SchedulePanel.vue Gantt-Zeitplan
├── UtilizationPanel.vue Auslastungs-Heatmap (urlaubsbereinigt)
├── VacationPanel.vue Urlaubsplanung inkl. Vertreterregelung
├── ProjectsPanel.vue Projekte/Aufgaben inkl. Zuweisungen
├── EmployeesPanel.vue Mitarbeiter
├── TeamsPanel.vue Teams (n:m-Mitgliedschaft)
├── UsersPanel.vue Benutzerverwaltung (nur Admin)
├── store.js Reaktiver State + CRUD gegen die API
├── api.js API-Client + Token-Handling
└── helpers.js Datum-/Gantt-/Farbberechnung
Lokale Entwicklung
Zwei Terminals.
1) Backend
cd server
npm install
npm run dev # startet auf http://localhost:8080
Beim ersten Start wird server/data/data.db angelegt und mit Beispieldaten befüllt.
Mit der Umgebungsvariable ADMIN_EMAIL (muss zur email eines bestehenden
Mitarbeiters passen) wird zusätzlich automatisch ein Start-Admin-Konto angelegt,
z. B.:
ADMIN_EMAIL=tom.fischer@example.com npm run dev
Ohne ADMIN_EMAIL wird kein Admin-Konto erzeugt — dann per
node scripts/reset-admin.js --employee-id <id> nachholen (siehe unten).
2) Frontend
cd client
npm install
npm run dev # startet auf http://localhost:5173
Browser auf http://localhost:5173 öffnen. Vite leitet /api und /health
per Proxy an das Backend weiter.
Deployment (Docker)
Die App läuft als ein Container: Das Backend serviert die REST-API und das
gebaute Frontend intern über Port 8080, nach außen gemappt auf Host-Port 8090
(siehe docker-compose.yml).
docker compose up --build
Danach ist die App unter http://localhost:8090 erreichbar. Die SQLite-Datenbank
liegt im Docker-Volume data. ADMIN_EMAIL vor dem ersten Start setzen (z. B.
in einer .env-Datei neben docker-compose.yml), damit ein Start-Admin für
einen bestehenden Mitarbeiter angelegt wird.
Umstieg von der alten Version (ohne Login)
Bestehende Projekte, Aufgaben, Zuweisungen, Teams und Mitarbeiter bleiben beim
Update unverändert erhalten — alle neuen Tabellen (users, sessions,
vacations) werden vom Server additiv angelegt (CREATE TABLE IF NOT EXISTS).
Damit nicht jedes bestehende Teammitglied einzeln über die Benutzerverwaltung
angelegt werden muss, legt folgendes Skript für alle Mitarbeiter mit
hinterlegter E-Mail automatisch ein Login-Konto an (Rolle mitarbeiter,
Passwort wird wie gewohnt beim ersten Login vergeben):
# lokal
node server/scripts/migrate-team-accounts.js
# im laufenden Container (Docker/Coolify)
docker exec <container> node scripts/migrate-team-accounts.js
Mitarbeiter ohne hinterlegte E-Mail werden übersprungen (Ausgabe zeigt wer) und
müssen die E-Mail zunächst im Mitarbeiter-Tab nachtragen. Mit --role teamleiter (oder admin/beobachter) lässt sich eine andere Standardrolle als
mitarbeiter vergeben; einzelne Rollen danach jederzeit über die
Benutzerverwaltung anpassen. Empfohlene Reihenfolge beim Umstieg: zuerst
ADMIN_EMAIL setzen bzw. reset-admin.js für den ersten Admin ausführen, dann
migrate-team-accounts.js für den Rest des Teams.
Admin-Zugang anlegen/zurücksetzen
Falls kein ADMIN_EMAIL gesetzt war oder das Passwort verloren ging:
# lokal
node server/scripts/reset-admin.js --employee-id 3
# im laufenden Container (Docker/Coolify)
docker exec <container> node scripts/reset-admin.js --employee-id 3
Ohne --password wird das Konto (neu) angelegt/verknüpft; das Passwort wird
beim nächsten Login vergeben. Mit --password wird sofort ein Passwort gesetzt
(Notfall-Wiederherstellung).
Deployment in Coolify
- Repository verbinden: Dieses Repo (
admin/ressourcenplanungauf Gitea) in Coolify als neue Ressource hinzufügen (New Resource → Application → Gitea-Repo auswählen). - Build-Pack: Docker Compose wählen. Das mitgelieferte
docker-compose.ymlbaut dasDockerfile(Multi-Stage: Vue-Build + Node-Server) und startet einen einzelnen Container. - Port: Der Container lauscht intern auf Port
8080, imdocker-compose.ymlauf Host-Port8090gemappt (Port 8080 war auf dem Host bereits durch eine andere Ressource belegt →driver failed programming external connectivity ... port is already allocated). In Coolify unter "Domains"/der Port-Konfiguration der Ressource muss der Host-Port (8090) explizit eingetragen werden — das passiert nicht automatisch. Falls auch 8090 belegt sein sollte, indocker-compose.ymleinen anderen freien Host-Port wählen (z. B."8091:8080") und die Coolify-Konfiguration entsprechend nachziehen. - Persistenz: Das Docker-Volume
datasichertserver/data/data.db(SQLite). Bei Redeploys bleiben die Daten erhalten, solange das Volume nicht gelöscht wird. Coolifys eingebaute Volume-Backup-Funktion kann dafür verwendet werden. - Healthcheck: Das Image bringt einen
HEALTHCHECKgegen/healthmit; Coolify nutzt ihn automatisch, um den Container-Status anzuzeigen. - Umgebungsvariable:
ADMIN_EMAILin Coolify unter den Environment-Variablen der Ressource setzen (E-Mail eines bestehenden Mitarbeiters) — damit wird beim ersten Start automatisch ein Start-Admin angelegt, der sein Passwort beim ersten Login selbst vergibt. OhneADMIN_EMAILbleibt die App ohne Admin-Konto; dannreset-admin.jsperdocker execnachholen (siehe oben). - Deploy klicken. Beim allerersten Start legt der Server automatisch
data.dban und befüllt sie mit Beispieldaten.