ソースを参照

claude.md

master
コミット
b17e9f1f50
1個のファイルの変更41行の追加6行の削除
  1. +41
    -6
      CLAUDE.md

+ 41
- 6
CLAUDE.md ファイルの表示

@@ -27,7 +27,7 @@ httpdocs/
│ ├── Repository/
│ │ ├── Central/
│ │ └── Tenant/
│ ├── Service/ # TenantContext, RegistrationService, etc.
│ ├── Service/ # TenantContext, RegistrationService, LexofficeService, etc.
│ ├── Doctrine/ # TenantConnectionMiddleware
│ ├── EventSubscriber/ # TenantRequestSubscriber, ArchivedUserSubscriber
│ ├── Security/ # ArchivedUserChecker, AccessDeniedHandler
@@ -42,7 +42,7 @@ httpdocs/
├── assets/
│ ├── app.js # Webpack-Entry für Timetracking
│ ├── styles/ # SCSS (main.scss als Entry)
│ └── scripts/ # JS-Module (calendar, entries, crud, stopwatch, team, account, report)
│ └── scripts/ # JS-Module (calendar, entries, crud, stopwatch, searchable-select, team, account, report)
├── migrations/
│ ├── central/ # Doctrine-Migrations für Central-DB
│ └── tenant/ # Doctrine-Migrations für Tenant-DB
@@ -136,10 +136,13 @@ Gemeinsame Hilfsfunktionen in `assets/scripts/utils.js`:
- `removeWithAnimation(el, className)` / `animateIn(el, className)` — Animierte DOM-Operationen
- Konstanten: `ANIMATION_MS`, `FADE_MS`, `MINUTES_PER_DAY`

### JS: searchable-select.js

Wiederverwendbares durchsuchbares Dropdown-Modul (`SearchableSelect`-Klasse) mit Gruppen, Keyboard-Navigation, Filter und `onSelect`-Callback. Wird von `stopwatch.js` (Projekt/Service-Auswahl) und `crud.js` (Lexoffice-Kontaktauswahl) importiert.

### JS: stopwatch.js

Stoppuhr-Modul mit zwei Klassen:
- `SearchableSelect` — Wiederverwendbares durchsuchbares Dropdown mit Gruppen, Keyboard-Navigation und Filter
Stoppuhr-Modul:
- `StopwatchManager` — Timer-Steuerung: Start/Stop/Resume, Tick-Display (Sekunden-Auflösung), DOM-Integration mit `window.entryManager`, Tab-Title-Update

### Globale `[hidden]`-Regel
@@ -162,7 +165,7 @@ Komplexe Logik die in mehreren Templates vorkommt wird in `templates/_macros/hel
| `member` | Eigene Einträge + alle fremden sehen (kein Team-Zugriff) |
| `tracker` | Nur eigene Einträge |

Superadmin = Account-Ersteller, kann Kontoinhaber übertragen und `primaryColor` setzen.
Superadmin = Account-Ersteller, kann Kontoinhaber übertragen, `primaryColor` und `lexofficeApiKey` setzen.

## Services-Injection (services.yaml)

@@ -185,7 +188,7 @@ Live-Timer zum Tracken von Zeiteinträgen. UI in der Navigation (Desktop + Hambu
### Architektur

- **Backend**: Timer-API im `TimeTrackingController` (`/api/timer/*`)
- **Frontend**: `assets/scripts/stopwatch.js` (importiert in `app.js`), enthält `SearchableSelect`-Klasse (durchsuchbare Dropdowns) und `StopwatchManager`
- **Frontend**: `assets/scripts/stopwatch.js` (importiert in `app.js`), nutzt `SearchableSelect` aus `searchable-select.js`
- **Styles**: `assets/styles/components/_stopwatch.scss`
- **Template**: Popover in `_sections/nav.html.twig`, Play-Button in `timetracking/_entry_row.html.twig`
- **Icon**: `_atoms/icon-stopwatch.html.twig`
@@ -209,6 +212,38 @@ Live-Timer zum Tracken von Zeiteinträgen. UI in der Navigation (Desktop + Hambu
- LocalStorage (`tt_timer_state`): persistiert Timer-State über Page-Reloads, wird mit Server-State abgeglichen
- LocalStorage (`tt_last_project_id`, `tt_last_service_id`): merkt letzte Auswahl für Quick-Start

## Lexoffice-Integration (Lexware Office)

Optionale Verknüpfung von Kunden mit Lexware Office Kontakten. Nur aktiv wenn `Account.lexofficeApiKey` gesetzt ist.

### Datenmodell

- `Account.lexofficeApiKey` (Central-DB): API-Key für Lexware Office, gespeichert pro Account
- `Client.lexofficeContactId` (Tenant-DB): UUID des verknüpften Lexware-Kontakts (nullable)

### Architektur

- **Service**: `LexofficeService` — HTTP-Client für Lexware Office API (`https://api.lexware.io/v1`), paginierter Kontakt-Abruf mit Rate-Limit-Retry
- **Controller**: `LexofficeController` — API-Endpunkte für Kontaktlisten und Einzelkontakte
- **Client-Controller**: `lexoffice-refresh`-Endpunkt zum Aktualisieren des Kundennamens aus Lexware
- **Frontend**: Lexoffice-Logik in `crud.js`, nutzt `SearchableSelect` für Kontakt-Dropdown
- **Account-Settings**: API-Key-Verwaltung im Account-Tab (Eingabe/Ändern mit Maskierung)

### API-Endpunkte

| Route | Method | Beschreibung |
|------------------------------------------|--------|-------------------------------------------|
| `/api/lexoffice/contacts` | GET | Alle Kunden-Kontakte aus Lexware Office |
| `/api/lexoffice/contacts/{contactId}` | GET | Einzelnen Kontakt abrufen |
| `/api/clients/{id}/lexoffice-refresh` | PATCH | Kundenname aus Lexware aktualisieren |

### Verhalten

- Beim Verknüpfen wird der Kundenname aus Lexware übernommen, das Name-Feld wird disabled
- Bereits verknüpfte Kontakte werden in der Dropdown-Liste ausgeblendet (Duplikat-Schutz)
- Reload-Button pro Zeile zum Aktualisieren des Namens aus Lexware
- Kontakte werden clientseitig gecacht (einmal geladen pro Page-Session)

## TenantConnectionMiddleware

Registriert via Service-Tag in `services.yaml` (nicht via `doctrine.yaml` — DoctrineBundle 3.x unterstützt `middlewares`-Config-Key nicht):


読み込み中…
キャンセル
保存