|
|
@@ -103,6 +103,7 @@ bash httpdocs/deploy.sh |
|
|
- **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. |
|
|
- **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) |
|
|
|
|
|
- **Labels**: Optionales Freitext-Label pro `TimeEntry` (max. 255 Zeichen). Autocomplete-Vorschläge basierend auf bisherigen Labels des gewählten Projekts (`/api/labels?projectId=X`) oder Freitextsuche (`/api/labels?q=X`). Chip-UI im Entry-Formular, Textfeld in der Stoppuhr. |
|
|
- **CSS Custom Properties**: Brand-Farben via `:root`-Variablen (`--color-primary`, etc.) |
|
|
- **CSS Custom Properties**: Brand-Farben via `:root`-Variablen (`--color-primary`, etc.) |
|
|
|
|
|
|
|
|
### Translations — keine hardcodierten Strings |
|
|
### Translations — keine hardcodierten Strings |
|
|
|