# 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** ```bash 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.: ```bash 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 ` nachholen (siehe unten). **2) Frontend** ```bash 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`). ```bash 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): ```bash # lokal node server/scripts/migrate-team-accounts.js # im laufenden Container (Docker/Coolify) docker exec 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: ```bash # lokal node server/scripts/reset-admin.js --employee-id 3 # im laufenden Container (Docker/Coolify) docker exec 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 1. **Repository verbinden**: Dieses Repo (`admin/ressourcenplanung` auf Gitea) in Coolify als neue Ressource hinzufügen (New Resource → Application → Gitea-Repo auswählen). 2. **Build-Pack**: **Docker Compose** wählen. Das mitgelieferte `docker-compose.yml` baut das `Dockerfile` (Multi-Stage: Vue-Build + Node-Server) und startet einen einzelnen Container. 3. **Port**: Der Container lauscht intern auf Port `8080`, im `docker-compose.yml` auf Host-Port `8090` gemappt (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, in `docker-compose.yml` einen anderen freien Host-Port wählen (z. B. `"8091:8080"`) und die Coolify-Konfiguration entsprechend nachziehen. 4. **Persistenz**: Das Docker-Volume `data` sichert `server/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. 5. **Healthcheck**: Das Image bringt einen `HEALTHCHECK` gegen `/health` mit; Coolify nutzt ihn automatisch, um den Container-Status anzuzeigen. 6. **Umgebungsvariable**: `ADMIN_EMAIL` in 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. Ohne `ADMIN_EMAIL` bleibt die App ohne Admin-Konto; dann `reset-admin.js` per `docker exec` nachholen (siehe oben). 7. **Deploy** klicken. Beim allerersten Start legt der Server automatisch `data.db` an und befüllt sie mit Beispieldaten.