# IMVS (MintyPHP)

IMVS ist eine mandantenfaehige Admin-Anwendung auf Basis von MintyPHP.
Der Fokus liegt auf klarer Rollen-/Rechtestruktur, Tenant-Scope und einer konsistenten Admin-UI.

## Funktionsumfang

- Mandantenverwaltung (inkl. Branding/Farbe/Favicon)
- Abteilungen pro Mandant
- Benutzerverwaltung mit Rollen, Sichtbarkeit und Stammdaten
- Rollen- und Berechtigungsverwaltung
- Adressbuch (tenant-scoped, read-only Profilansicht)
- Globale Suche (Admin + Address Book)
- Mail-Versand (SMTP/PHPMailer) inkl. Mail-Log
- Onboarding-PDF fuer Zugangsdaten (Single inline, Bulk als ZIP)
- Passwort-Reset und Remember-Login-Tokens

## Tech Stack

- PHP 8.5 (Runtime im Docker-Container)
- MintyPHP Core
- MariaDB 11
- Memcached
- Nginx
- Grid.js (Tabellen)
- PHPMailer
- Dompdf (PDF Rendering)
- endroid/qr-code (QR-Code Rendering)

## Schnellstart (Docker)

1. Umgebungsdatei anlegen

```bash
cp .env.example .env
```

2. Container starten

```bash
docker compose up --build -d
```

3. App oeffnen

- App: [http://localhost:8080](http://localhost:8080)
- phpMyAdmin: [http://localhost:8081](http://localhost:8081)

4. Container stoppen

```bash
docker compose down
```

## Produktion (Docker)

Es gibt eine getrennte Produktions-Compose:

- Dev: `/docker-compose.yml`
- Prod: `/docker-compose.prod.yml`

Grundschritte:

1. `.env` auf Produktionswerte setzen (siehe `/.env.prod.example`)
2. Domain und TLS in `/docker/nginx/prod.conf` anpassen
3. Zertifikate unter `/docker/nginx/certs/` bereitstellen
4. Starten:

```bash
docker compose -f docker-compose.prod.yml up --build -d
```

Details stehen in:

- `/docs/docker-lokal.md`
- `/docs/docker-produktiv.md`
- `/docs/docker-betrieb.md` (Übersicht)

## Seed-Daten

Die Initialisierung liegt in `/db/init/init.sql`.

Standard-Demo-User:

- E-Mail: `demo@user.com`
- Passwort: `Demo123`
- Tenant: `Cronus`
- Abteilung: `IT`
- Rolle: `Admin`

## Projektstruktur

- `/config` Konfiguration (Routen, Settings, Themes, Assets)
- `/db/init` Datenbankschema + Seeds
- `/lib` Backend-Code (`Repository`, `Service`, `Http`, `Support`)
- `/pages` Action-Layer + Views pro Route
- `/templates` Layouts + wiederverwendbare Partials
- `/web` oeffentliche Assets (CSS/JS/Vendor)
- `/i18n` Uebersetzungen
- `/tests` PHPUnit-Tests
- `/docs` Projekt-Dokumentation

## Architektur-Kurzregeln

- Keine DB-Zugriffe in `.phtml`-Views.
- SQL bleibt in Repositories.
- Geschaeftslogik bleibt in Services.
- `pages/.../*.php` fungiert als Action-/Controller-Schicht.
- Permissions + Tenant-Scope werden in Actions/Services erzwungen.
- Wiederkehrende UI-Bloecke als Partials zentralisieren.

## UI-Konventionen

Edit-Seiten verwenden einheitliche Tab-Struktur:

- erster Tab: `Master data`
- letzter Tab: `Visibility`
- optional letzter Tab: `Danger zone`

User-Organisation:

- Departments werden tenantweise angezeigt (ein Multi-Select je ausgewaehltem Tenant).
- Nach Tenant-Aenderungen im selben Formular werden Department-Optionen nach Speichern/Reload aktualisiert (kein Live-Update).

Zentrale Partials:

- `/templates/partials/app-details-titlebar.phtml`
- `/templates/partials/app-visibility-status-field.phtml`
- `/templates/partials/app-danger-zone-delete-field.phtml`
- `/templates/partials/app-details-aside-audit.phtml`
- `/templates/partials/app-details-aside-ids.phtml`

## Onboarding-PDF (User)

- Permission: `users.access_pdf`
- Single: `admin/users/access-pdf/{uuid}` (inline im neuen Tab)
- Bulk: `admin/users/access-pdf-bulk` (POST, ZIP mit einer PDF pro User)
- Hard limit: maximal 100 User pro Bulk-Request
- Benoetigte Extensions: `ext-zip`, `ext-dom`, `ext-mbstring`
- Bestehende Installationen: Schema-/Permission-Updates als idempotentes SQL-Update ausfuehren

## Microsoft SSO (Tenant, Entra ID)

- Zentraler Einstieg: `login` (optional mit Tenant-Hint `login?tenant={tenant-slug}`)
- OIDC-Endpunkte: `auth/microsoft/start` und `auth/microsoft/callback`
- Tenant-Config liegt in `tenant_auth_microsoft`
- Externe User-Linkung liegt in `user_external_identities`
- Optionaler Profil-Sync pro Tenant:
  - `sync_profile_on_login` aktiviert Sync bei jedem Microsoft-Login
  - `sync_profile_fields`: `first_name`, `last_name`, `phone`, `mobile`, `avatar`
  - Default-Felder bei aktivem Sync ohne Auswahl: `first_name,last_name`
  - `phone/mobile/avatar` nutzen Microsoft Graph (`User.Read`)
- Shared App Credentials werden in Settings gepflegt (optional Tenant-Overrides)
- Permission fuer Tenant-SSO-Konfiguration: `tenants.sso_manage`
- Bestandsinstallationen: Schema-/Permission-Updates als idempotentes SQL-Update ausfuehren
- Wichtig: `APP_CRYPTO_KEY` in `.env` setzen, sonst koennen SSO-Secrets nicht gespeichert/verwendet werden

## Asset- und Frontend-System

- CSS-Layer-Entrypoint: `/web/css/app-layers.css`
- Vendor-Overrides: `/web/css/vendor-overrides`
- Asset-Gruppen: `/config/assets.php`
- Template-Styles: `renderTemplateStyles('default'|'login')`
- Seiten-Styles per Action: `Buffer::set('style_groups', ...)`
- JS-Bootstrap:
  - `/web/js/app-boot.js` (frueh, ohne Module)
  - `/web/js/app-init.js` (Standardseiten)
  - `/web/js/app-login-init.js` (Loginseiten)

## Qualitaetschecks

Alle Befehle aus dem Projekt-Root ausfuehren.

### PHPUnit

```bash
docker compose exec php vendor/bin/phpunit --bootstrap vendor/autoload.php
```

Gezielt:

```bash
docker compose exec php vendor/bin/phpunit --bootstrap vendor/autoload.php tests/I18n/TranslationKeysTest.php
docker compose exec php vendor/bin/phpunit --bootstrap vendor/autoload.php tests/Repository/RepoQueryTest.php
```

### PHPStan

```bash
docker compose exec php vendor/bin/phpstan analyse -c phpstan.neon --no-progress
```

### ESLint (Frontend-JS)

```bash
npx eslint web/js
```

## Dokumentation

- `/docs/index.md` Einstieg und Dokumentationsindex
- `/docs/architektur.md` Request-Flow und Layering
- `/docs/konventionen.md` Coding- und UI-Konventionen
- `/docs/sicherheitsmodell.md` Auth/Permission/Tenant-Scope
- `/docs/entwickler-checkliste.md` konkrete Checkliste fuer Aenderungen
- `/docs/benutzerdefinierte-felder.md` Quick Reference fuer Tenant/User-Zusatzfelder
- `/docs/api.md` API v1 Referenz (inkl. Self-Service Token-Endpunkte)
- `/docs/einstellungen-speicherung.md` Globale Settings: DB als Quelle, `config/settings.php` als Teil-Cache
- `/docs/frontend-javascript.md` Frontend-JS-Struktur
- `/docs/frontend-css.md` Frontend-CSS-Struktur
- `/docs/docker-lokal.md` Docker lokal (Entwicklung)
- `/docs/docker-produktiv.md` Docker produktiv (Serverbetrieb)
- `/docs/docker-betrieb.md` Dev/Prod Docker-Betrieb

## Troubleshooting

- Verhalten wirkt stale nach groesseren Refactors:

```bash
docker compose restart php nginx
```

- Uebersetzungs-Keys fehlen:

```bash
docker compose exec php vendor/bin/phpunit --bootstrap vendor/autoload.php tests/I18n/TranslationKeysTest.php
```

- Favicon/Logo aus Storage fehlt:
  - Symlink und Tenant-Kontext pruefen (`web/favicon/tenants -> storage/tenants`).

## Lizenz

MIT (siehe `/LICENSE.md`)
