Konzept: Zeiterfassung (§14) + überarbeitetes Rechte-Konzept (§2)
- §14 Zeiterfassung (Kommen/Gehen): TimeEntry append-only/revisionssicher, Stempeln per App/Kiosk/Web (NFC/PIN), Compliance (ArbZG/DSGVO/BetrVG) - §2 neu: mehrere Logins pro Ebene, Rechtegruppen, delegierte Rechtevergabe (Rolle <= eigene Ebene + nur eigener Mandanten-Teilbaum), RoleAssignmentVoter Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
79e996ab03
commit
46a75f859b
112
docs/KONZEPT.md
112
docs/KONZEPT.md
@ -32,9 +32,44 @@
|
||||
|
||||
**Hierarchie der Mandanten:** `Plattform → Reseller → Company → Location → Employee/Profil`
|
||||
|
||||
### Mehrere Logins pro Ebene
|
||||
|
||||
Jede Ebene kann **mehrere Benutzer** haben (mehrere Plattform-, Reseller-, Firmen-Admins).
|
||||
Technisch: `User` ist die Login-Identität (1 Person = 1 Login), `n` User pro
|
||||
Reseller bzw. Company. Ein `User` ist optional mit einem `Employee` (Profil) verknüpft —
|
||||
so wird aus einem Mitarbeiter mit Profil per **Rechtegruppen-Zuweisung** zusätzlich
|
||||
ein eingeloggter Admin.
|
||||
|
||||
### Rechtegruppen (zuweisbare Rollen)
|
||||
|
||||
Die Rollen werden im UI als wählbare **Rechtegruppe** angeboten — beim Anlegen/Bearbeiten
|
||||
eines Benutzers bzw. direkt in der Mitarbeiterliste („kein Login" | „Mitarbeiter" |
|
||||
„Firmen-Admin" | …). Start = die vier festen Rollen; später optional **granulare
|
||||
Berechtigungs-Gruppen** (eigene Rechte-Sets pro Mandant).
|
||||
|
||||
### Delegierte Rechtevergabe (Kernregel)
|
||||
|
||||
Jede Ebene vergibt Rechte **nur an oder unterhalb der eigenen Ebene** und **nur im
|
||||
eigenen Mandanten-Teilbaum** — niemals nach oben, nie über Mandantengrenzen hinweg:
|
||||
|
||||
| Akteur | darf Rechtegruppe vergeben | Geltungsbereich |
|
||||
|--------|----------------------------|-----------------|
|
||||
| Plattform-Admin | Plattform-Admin, Reseller-Admin (+ darunter) | alle Mandanten |
|
||||
| Reseller-Admin | Reseller-Admin (weitere im eigenen Reseller), Firmen-Admin, Mitarbeiter | nur eigener Reseller + dessen Firmen |
|
||||
| Firmen-Admin | Firmen-Admin (weitere der eigenen Firma), Mitarbeiter | nur eigene Firma |
|
||||
| Mitarbeiter | — | — |
|
||||
|
||||
D. h.: *wir* vergeben Reseller-Rechte, Reseller vergeben Firmen-Admin-Rechte, Firmen-Admins
|
||||
vergeben Mitarbeiter-/weitere Firmen-Admin-Rechte. Same-Level-Vergabe (weitere Admins der
|
||||
eigenen Ebene) ist erlaubt → ermöglicht mehrere Logins pro Ebene.
|
||||
|
||||
Durchsetzung über:
|
||||
- **Doctrine-Filter** (automatisches Scoping nach `reseller_id` / `company_id` je nach eingeloggtem Kontext)
|
||||
- **Security Voters** (z. B. `ProfileVoter`, `CompanyVoter`) für feingranulare Aktionen
|
||||
- **Doctrine-Filter / API-Platform-Query-Extension** (automatisches Scoping nach
|
||||
`reseller_id` / `company_id` je nach eingeloggtem Kontext)
|
||||
- **Security Voters** (`CompanyVoter`, `EmployeeVoter`) für Aktion×Objekt
|
||||
- **`RoleAssignmentVoter`/-Service**: prüft bei jeder Rollen-/Rechtegruppen-Vergabe,
|
||||
dass die Zielrolle ≤ der höchsten Rolle des Akteurs ist **und** der Ziel-Benutzer im
|
||||
Mandanten-Teilbaum des Akteurs liegt (Schutz vor Privilege-Escalation)
|
||||
- API-Platform `security`-Attribute pro Resource & Operation
|
||||
|
||||
---
|
||||
@ -75,7 +110,7 @@ und legen sie versioniert ab. Öffentliche Endpunkte liefern immer den aktuellen
|
||||
|
||||
### Kernentitäten
|
||||
|
||||
- **User** — Auth-Identität. Felder: `email`, `password`, `roles[]`, `status`, `lastLogin`. Verknüpft optional mit `reseller_id`, `company_id`, `employee_id` (je nach Rolle).
|
||||
- **User** — Auth-Identität (1 Login). Felder: `email`, `password`, `roles[]` (= Rechtegruppe), `status`, `lastLogin`. Verknüpft optional mit `reseller_id`, `company_id`, `employee_id`. **Mehrere User pro Reseller/Company** möglich; Rollenvergabe ist delegiert & scope-geprüft (siehe §2).
|
||||
- **Reseller** — oberster Mandant. Felder: `name`, `slug`, `primaryDomain`, Branding-Defaults, `status`, `platformPlan_id`. Hat Limits aus dem Plattform-Paket.
|
||||
- **PlatformPlan** — Reseller-Pakete (Starter/Professional/Business). Felder: `name`, `pricePerMonth`, `maxProfiles`, `maxCompanies`, `features[]`.
|
||||
- **ResellerSubscription** — Abo des Resellers bei der Plattform. Felder: `plan_id`, `status`, `startedAt`, `renewsAt`, `paymentRef` (Stripe).
|
||||
@ -391,3 +426,74 @@ Font-Embedding ist zugleich Voraussetzung für striktes **PDF/X**.
|
||||
`CardTemplate.fonts` (`[{family, path}]`). Dateien liegen außerhalb des Webroots unter
|
||||
`var/storage/cards/{companyId}/`. Upload-Endpunkte:
|
||||
`POST /api/companies/{id}/card-template/background` (PDF) und `.../font` (TTF/OTF).
|
||||
|
||||
---
|
||||
|
||||
## 14. Zeiterfassung (Modul „Kommen/Gehen")
|
||||
|
||||
Erweiterung über die digitale Visitenkarte hinaus: eine **Arbeitszeiterfassung**
|
||||
für die Firmenkunden der Reseller (vorzugsweise Druckshops). Der Mitarbeiter ist
|
||||
die gemeinsame Klammer — dieselbe Identität (`Employee`), dieselben Standorte,
|
||||
dieselbe NFC/QR-Infrastruktur. Positioniert die Plattform vom „Identity/Print-Tool"
|
||||
hin zur **Mitarbeiter-Plattform** (ein Datensatz, mehrere Module).
|
||||
|
||||
### Markttreiber
|
||||
EuGH 2019 + BAG 2022 → **Pflicht zur Arbeitszeiterfassung** in DE. SMB-Kunden
|
||||
suchen einfache Lösungen → starkes Verkaufsargument; NFC-Terminals/Badges sind
|
||||
zusätzlicher **Hardware-Umsatz** für den Druckshop.
|
||||
|
||||
### Erfassungswege
|
||||
- **Web/App** (authentifizierter Mitarbeiter über sein `User`-Konto): Button
|
||||
„Kommen / Gehen / Pause" im Dashboard bzw. Handy-Browser. Quelle `web`/`app`.
|
||||
- **Kiosk** (geteiltes Standort-Gerät, per Geräte-Token): Mitarbeiter identifiziert
|
||||
sich per **NFC-Tap** (`shortCode`) oder **PIN**. Quelle `kiosk`.
|
||||
- NFC/QR nutzt die bestehende `shortCode`/`/t/`-Infrastruktur. *Hinweis:* da der
|
||||
Profil-`shortCode` halb-öffentlich ist, am Kiosk zusätzlich **PIN** empfehlen.
|
||||
|
||||
### Datenmodell
|
||||
|
||||
**`TimeEntry`** — append-only Stempel-Ereignis (revisionssicher, **kein** Update/Delete):
|
||||
`employee`, `type` (`clock_in`|`clock_out`|`break_start`|`break_end`),
|
||||
`occurredAt` (Stempelzeit), `recordedAt` (Speicherzeit, immutable),
|
||||
`source` (`web`|`app`|`kiosk`|`nfc`|`qr`|`manual`), `location` (nullable),
|
||||
`createdBy` (User), `note`, `status` (`active`|`corrected`|`voided`),
|
||||
`correctsEntry` (self-ref, nullable), `reason` (bei Korrektur/Storno).
|
||||
|
||||
**`KioskDevice`** — registriertes Standort-Terminal: `name`, `token`, `location`,
|
||||
`status`, `lastSeenAt`.
|
||||
|
||||
**`Employee`-Ergänzung:** `clockPin` (optional, für Kiosk/App-Identifikation).
|
||||
|
||||
**Korrekturprinzip:** Originale bleiben erhalten; eine Korrektur erzeugt einen
|
||||
**neuen** `TimeEntry` (`type=correction`-Bezug via `correctsEntry`) mit Grund +
|
||||
Bearbeiter, der alte wird als `corrected` markiert. Der „gültige" Stundenzettel
|
||||
wird aus den `active`-Einträgen berechnet. Jede Markierung ist protokolliert →
|
||||
nachvollziehbar/manipulationssicher.
|
||||
|
||||
### Endpunkte (grob)
|
||||
- `POST /api/time-clock/punch` — eingeloggter Mitarbeiter stempelt (Typ ermittelt
|
||||
oder explizit), Quelle web/app.
|
||||
- `POST /api/kiosk/punch` — Geräte-Token + Mitarbeiter-Kennung (NFC-`shortCode`/PIN).
|
||||
- `GET /api/time-entries` — mandantengescoped (Mitarbeiter: eigene; Firmen-Admin: alle).
|
||||
- `GET /api/timesheets?employee=&period=` — Aggregation (Tag/Woche, Überstunden, je Standort).
|
||||
- `POST /api/time-entries/{id}/correct` — Firmen-Admin, hängt Korrektur an (Audit).
|
||||
|
||||
### Rollen
|
||||
- **Mitarbeiter**: stempelt, sieht eigene Zeiten (Transparenzpflicht).
|
||||
- **Firmen-Admin**: Stundenzettel, Korrekturen (mit Grund/Audit), Export, Kiosk-Geräte.
|
||||
- **Reseller/Plattform**: white-label Einstellungen, Limits.
|
||||
|
||||
### Compliance (bewusst zu behandeln)
|
||||
- **Revisionssicherheit**: append-only + protokollierte Korrekturen (s. o.).
|
||||
- **ArbZG**: Pausen/Höchstarbeits-/Ruhezeiten erfassbar bzw. warnend.
|
||||
- **DSGVO + BetrVG §87** (Mitbestimmung): kein heimliches Tracking, Einsicht für
|
||||
Mitarbeiter, Standort EU, Lösch-/Exportkonzept.
|
||||
|
||||
### Auswertung & Export
|
||||
Stundenzettel (Tag/Woche/Monat), Überstunden, Pausensummen je Mitarbeiter/Standort;
|
||||
Export CSV/PDF — später Lohn-Schnittstelle (z. B. DATEV).
|
||||
|
||||
### MVP-Abgrenzung
|
||||
**Drin:** Kommen/Gehen/Pause über Web/App/Kiosk (NFC/PIN), Stundenzettel,
|
||||
revisionssichere Korrektur, CSV/PDF-Export. **Draußen (Folgeschritte):** Urlaub/
|
||||
Krankmeldung, Schicht-/Dienstplanung, Projektzeiten, DATEV-Export, Geofencing.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user