|
|
@@ -101,6 +101,7 @@ bash httpdocs/deploy.sh |
|
|
- **Rounding**: Konfigurierbar per `Account.trackingInterval` (1/15/30/60 Min) |
|
|
- **Rounding**: Konfigurierbar per `Account.trackingInterval` (1/15/30/60 Min) |
|
|
- **API-Pattern**: `/api/...` Routen, JSON Request/Response, kein CSRF auf API-Endpunkten |
|
|
- **API-Pattern**: `/api/...` Routen, JSON Request/Response, kein CSRF auf API-Endpunkten |
|
|
- **Timer/Stoppuhr**: `TimeEntry.timerStartedAt` (nullable `DateTimeImmutable`) markiert laufende Timer. Pro User nur ein aktiver Timer gleichzeitig. Elapsed wird beim Stoppen auf `trackingInterval` gerundet und zu `duration` addiert. |
|
|
- **Timer/Stoppuhr**: `TimeEntry.timerStartedAt` (nullable `DateTimeImmutable`) markiert laufende Timer. Pro User nur ein aktiver Timer gleichzeitig. Elapsed wird beim Stoppen auf `trackingInterval` gerundet und zu `duration` addiert. |
|
|
|
|
|
- **Stundensätze (hourlyRate)**: Dreistufige Kaskade `Project.hourlyRate → Client.hourlyRate → Service.hourlyRate` (via `COALESCE`). Kunden und Projekte haben einen Rate-Mode-Toggle (Standard-Sätze vs. eigener Stundensatz), Services immer ein direktes Feld. Revenue-Berechnung in `TimeEntryRepository::sumRevenueFiltered()` nutzt die Kaskade. |
|
|
- **Rollen**: `admin` (alles), `member` (eigene + fremde Einträge sehen), `tracker` (nur eigene) |
|
|
- **Rollen**: `admin` (alles), `member` (eigene + fremde Einträge sehen), `tracker` (nur eigene) |
|
|
- **CSS Custom Properties**: Brand-Farben via `:root`-Variablen (`--color-primary`, etc.) |
|
|
- **CSS Custom Properties**: Brand-Farben via `:root`-Variablen (`--color-primary`, etc.) |
|
|
|
|
|
|
|
|
|