20-02-2026

This commit is contained in:
Kevin Adametz 2026-02-20 17:55:06 +01:00
parent a8b395e20d
commit a00c42e770
252 changed files with 28785 additions and 8907 deletions

View file

@ -0,0 +1,412 @@
# Benutzer-Spracheinstellung für Dokumente
**Datum:** 04.02.2026
**Bezug:** next-steps.md - Punkt 6: Mehrsprachigkeit: Rechnungen, Provisionen, Lieferscheine
## Übersicht
Diese Implementierung fügt ein Sprachfeld zu den Benutzerdaten hinzu, damit Benutzer selbst entscheiden können, in welcher Sprache sie ihre Dokumente (Rechnungen, Provisionsabrechnungen, Lieferscheine) erhalten möchten.
## Problem
Bisher wurde die Sprache für Dokumente immer von der aktuellen Session-Sprache übernommen (`\App::getLocale()`). Das Problem dabei:
- Benutzer, die auf Deutsch surfen aber Spanisch bevorzugen, bekommen Dokumente auf Deutsch
- Die Spracheinstellung ist nicht persistent
## Lösung
### 1. Datenbankänderung
**Migration 1:** `2026_02_04_101805_add_language_to_user_accounts_table.php`
```php
Schema::table('user_accounts', function (Blueprint $table) {
$table->string('language', 5)->nullable()->after('notice');
});
```
**Migration 2:** `2026_02_04_102455_change_language_default_on_user_accounts_table.php`
Setzt den Default auf NULL (statt 'de'), damit die aktuelle App-Locale (`\App::getLocale()`) als Fallback verwendet wird.
### 2. Model-Anpassungen
#### UserAccount & ShoppingUser
Beide Models haben jetzt:
```php
// Accessor - gibt App-Locale zurück wenn NULL:
public function getLanguageAttribute($value): string
{
return $value ?: \App::getLocale();
}
// Alias für Konsistenz:
public function getLocale(): string
{
return $this->language;
}
// Sprachen werden aus config/localization.php geladen:
public static function getAvailableLanguages(): array
{
$locales = config('localization.supportedLocales', []);
$languages = [];
foreach ($locales as $code => $locale) {
$languages[$code] = $locale['native'] ?? $locale['name'] ?? $code;
}
return $languages;
}
```
### 3. Frontend-Formulare
| Formular | Datei | Beschreibung |
| -------------------- | ----------------------------------------------------------- | ------------------------------------------------ |
| Berater-Profil | `resources/views/user/user_form.blade.php` | Sprachauswahl zwischen Bankdaten und Steuerdaten |
| Kunden-Bearbeitung | `resources/views/admin/customer/_edit.blade.php` | Sprachauswahl nach Bemerkungen |
| Kunden-Detailansicht | `resources/views/admin/customer/_customer_detail.blade.php` | Sprache wird bei Rechnungsadresse angezeigt |
| Checkout | `resources/views/web/templates/checkout.blade.php` | Sprachauswahl im Bestellformular |
### 4. Übersetzungen
**account.php** (für Berater-Profil):
| Key | DE | EN | ES |
| -------------------- | ----------------------------------------- | ----------------------------------------------- | --------------------------- |
| `language_settings` | Spracheinstellungen | Language settings | Configuración de idioma |
| `preferred_language` | Bevorzugte Sprache | Preferred language | Idioma preferido |
| `language_hint` | Diese Sprache wird für Ihre Rechnungen... | This language will be used for your invoices... | Este idioma se utilizará... |
**customer.php** (für Kunden-Verwaltung):
| Key | DE | EN | ES |
| --------------- | --------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------------- |
| `language_hint` | Die Rechnungen und Dokumente werden in dieser Sprache erstellt. | Invoices and documents will be created in this language. | Las facturas y documentos se crearán en este idioma. |
## Verfügbare Sprachen
Die verfügbaren Sprachen werden aus `config/localization.php` unter `supportedLocales` geladen.
Aktuell aktiv:
- `de` - Deutsch
- `en` - English
- `es` - Español
## Verhalten
### UserAccount (Berater/Consultants)
- Benutzer können ihre bevorzugte Sprache im Profil unter "Spracheinstellungen" auswählen
- `$user->account->language` gibt immer einen Wert zurück (nie NULL dank Accessor)
- Wird für Provisionsabrechnungen verwendet
### ShoppingUser (Kunden)
- Berater können bei Kunden eine bevorzugte Sprache hinterlegen
- Im Checkout kann der Kunde die Sprache selbst wählen
- `$shopping_user->language` gibt immer einen Wert zurück (nie NULL dank Accessor)
- Wird für Rechnungen und Lieferscheine verwendet
## Geänderte Dateien
| Datei | Änderung |
| ------------------------------------------------------------------------------------------ | -------------------------------------------------- |
| `database/migrations/2026_02_04_101805_add_language_to_user_accounts_table.php` | Neue Migration - Feld hinzufügen |
| `database/migrations/2026_02_04_102455_change_language_default_on_user_accounts_table.php` | Default auf NULL ändern |
| `app/Models/UserAccount.php` | Accessor, `getLocale()`, `getAvailableLanguages()` |
| `app/Models/ShoppingUser.php` | Accessor, `getAvailableLanguages()` |
| `resources/views/user/user_form.blade.php` | Sprachauswahl für Berater |
| `resources/views/admin/customer/_edit.blade.php` | Sprachauswahl für Kunden |
| `resources/views/admin/customer/_customer_detail.blade.php` | Sprache in Detailansicht |
| `resources/views/web/templates/checkout.blade.php` | Sprachauswahl im Checkout |
| `resources/lang/de/account.php` | Neue Übersetzungen |
| `resources/lang/en/account.php` | Neue Übersetzungen |
| `resources/lang/es/account.php` | Neue Übersetzungen |
| `resources/lang/de/customer.php` | Neue Übersetzung `language_hint` |
| `resources/lang/en/customer.php` | Neue Übersetzung `language_hint` |
| `resources/lang/es/customer.php` | Neue Übersetzung `language_hint` |
## Test
### UserAccount (Berater-Profil)
1. Als Berater einloggen
2. Profil bearbeiten (Route: `/user/edit`)
3. Neue Sektion "Spracheinstellungen" sichtbar
4. Sprache auswählen und speichern
5. Prüfen: Feld wird in `user_accounts.language` gespeichert
### ShoppingUser (Kunden-Verwaltung)
1. Als Berater einloggen
2. Kunde bearbeiten oder anlegen
3. Sprachauswahl im Formular sichtbar
4. Sprache auswählen und speichern
5. Prüfen: Feld wird in `shopping_users.language` gespeichert
### Checkout
1. Shop aufrufen und Produkte in den Warenkorb legen
2. Zur Kasse gehen
3. Sprachauswahl im Rechnungsadresse-Bereich sichtbar
4. Sprache auswählen
5. Bestellung abschließen
6. Prüfen: Rechnung wird in der gewählten Sprache erstellt
## Phase 2: Mehrsprachige PDF-Erstellung
### Konzept
Für finanzrechtliche Anforderungen wird **immer** ein deutsches Original erstellt. Wenn der Kunde/Benutzer eine andere Sprache bevorzugt, wird zusätzlich eine Kopie in seiner Landessprache generiert.
### Dateinamen-Schema
| Dokument | Deutsch (Original) | Kundensprache (z.B. ES) |
| ------------ | ----------------------------------- | -------------------------------------- |
| Rechnung | `202600123-MIVITA-Rechnung.pdf` | `202600123-MIVITA-Rechnung-es.pdf` |
| Lieferschein | `202600123-MIVITA-Lieferschein.pdf` | `202600123-MIVITA-Lieferschein-es.pdf` |
| Gutschrift | `GS202600123-MIVITA-Gutschrift.pdf` | `GS202600123-MIVITA-Gutschrift-es.pdf` |
### Implementierung
#### Invoice Service (`app/Services/Invoice.php`)
Neue Methoden für lokalisierte Dateinamen:
```php
public static function makeInvoiceFilenameLocale($invoice_number, $locale)
public static function makeDeliveryFilenameLocale($invoice_number, $locale)
```
#### Credit Service (`app/Services/Credit.php`)
Neue Methode für lokalisierte Gutschrift-Dateinamen:
```php
public static function makeCreditFilenameLocale($credit_number, $locale)
```
#### InvoiceRepository (`app/Repositories/InvoiceRepository.php`)
Die `makePDF()` Methode erstellt jetzt:
1. Deutsches Original (immer)
2. Lokalisierte Kopie (wenn Kundensprache ≠ DE)
Neue Helper-Methoden:
```php
private function createPDFFiles(array $data, string $locale)
private function getTemplateForLocale(string $locale): string
```
#### CreditRepository (`app/Repositories/CreditRepository.php`)
Die `create()` Methode erstellt jetzt:
1. Deutsches Original (immer)
2. Lokalisierte Kopie (wenn Benutzersprache ≠ DE)
Neue Helper-Methoden:
```php
private function createCreditPDF(array $data, string $path, string $dir, string $filename, string $locale, bool $is_copy)
private function getTemplateForLocale(string $locale): string
```
### PDF-Templates nach Sprache
Die Templates für den PDF-Merger werden automatisch basierend auf der Sprache gewählt.
**Konfiguration** in `config/localization.php`:
```php
'availableTemplates' => ['de', 'en', 'es', 'fr'],
```
| Sprache | Template |
| ----------- | -------------------------------- |
| Deutsch | `template_invoice_de` |
| Englisch | `template_invoice_en` |
| Spanisch | `template_invoice_es` |
| Französisch | `template_invoice_fr` |
| Sonstige | `template_invoice_de` (Fallback) |
#### UserInvoice Model (`app/Models/UserInvoice.php`)
Neue Methoden für lokalisierten Zugriff:
```php
public function getDownloadPathLocale($locale = null, $full = false)
public function getDownloadPathDeliveryLocale($locale = null, $full = false)
public function getFilenameLocale($locale = null)
```
#### UserCredit Model (`app/Models/UserCredit.php`)
Neue Methoden für lokalisierten Zugriff:
```php
public function getDownloadPathLocale($locale = null, $full = false)
public function getFilenameLocale($locale = null)
```
#### MailInvoice (`app/Mail/MailInvoice.php`)
Versendet **beide Versionen** als Anhänge:
1. Deutsches Original (immer)
2. Lokalisierte Kopie (wenn Kundensprache ≠ DE und Datei existiert)
#### MailCredit (`app/Mail/MailCredit.php`)
Versendet **beide Versionen** als Anhänge:
1. Deutsches Original (immer)
2. Lokalisierte Kopie (wenn Benutzersprache ≠ DE und Datei existiert)
### Kopie-Kennzeichnung in PDFs
Lokalisierte Kopien werden mit einem Hinweis über dem Datum gekennzeichnet:
| Dokumenttyp | Hinweis (in Kundensprache) |
| ------------ | -------------------------- |
| Rechnung | "Invoice copy: EN" |
| Lieferschein | "Delivery note copy: EN" |
| Gutschrift | "Credit note copy: EN" |
**Übersetzungen** (`resources/lang/*/pdf.php`):
| Key | DE | EN | ES |
| --------------- | ----------------- | ------------------ | --------------------------- |
| `invoice_copy` | Rechnungskopie | Invoice copy | Copia de factura |
| `delivery_copy` | Lieferscheinkopie | Delivery note copy | Copia del albarán |
| `credit_copy` | Gutschriftkopie | Credit note copy | Copia de la nota de crédito |
### Geänderte Dateien (Phase 2)
| Datei | Änderung |
| ---------------------------------------- | ------------------------------------------------------------- |
| `app/Services/Invoice.php` | `makeInvoiceFilenameLocale()`, `makeDeliveryFilenameLocale()` |
| `app/Services/Credit.php` | `makeCreditFilenameLocale()` |
| `app/Repositories/InvoiceRepository.php` | Mehrsprachige PDF-Erstellung mit `is_copy` Flag |
| `app/Repositories/CreditRepository.php` | Mehrsprachige Gutschrift-Erstellung mit `is_copy` Flag |
| `app/Models/UserInvoice.php` | Lokalisierte Pfad-Methoden |
| `app/Models/UserCredit.php` | Lokalisierte Pfad-Methoden |
| `app/Mail/MailInvoice.php` | DE Original + lokalisierte Version als Anhänge |
| `app/Mail/MailCredit.php` | DE Original + lokalisierte Version als Anhänge |
| `resources/views/pdf/invoice.blade.php` | Kopie-Hinweis über Datum |
| `resources/views/pdf/delivery.blade.php` | Kopie-Hinweis über Datum |
| `resources/views/pdf/credit.blade.php` | Kopie-Hinweis über Datum |
| `resources/lang/de/pdf.php` | Übersetzungen für Kopie-Hinweise |
| `resources/lang/en/pdf.php` | Übersetzungen für Kopie-Hinweise |
| `resources/lang/es/pdf.php` | Übersetzungen für Kopie-Hinweise |
### Ablauf nach Implementierung
```
Bestellung → InvoiceRepository::create()
makePDF()
┌────────────┴────────────┐
│ │
▼ ▼
DE PDF (Original) Kundensprach-PDF (Kopie)
mit "Rechnungskopie: ES"
│ │
└────────────┬────────────┘
sendInvoiceMail()
Anhänge: DE Original + Kundensprach-Kopie
```
### Test
1. Kunde mit Spanisch (`es`) als bevorzugte Sprache anlegen
2. Bestellung für diesen Kunden abschließen
3. Prüfen:
- Im Speicherordner existieren beide PDFs: `*-Rechnung.pdf` und `*-Rechnung-es.pdf`
- Das spanische PDF enthält den Hinweis "Copia de factura: ES" über dem Datum
- Die E-Mail enthält **beide** Anhänge (DE Original + ES Kopie)
4. Im Admin sind beide Versionen verfügbar (DE für Finanzamt, ES für Kundenservice)
## Phase 3: Admin-Download-Buttons für lokalisierte PDFs
### Route-Erweiterung
Die `storage_file` Route wurde um einen optionalen `locale` Parameter erweitert:
```php
// routes/shared/common.php
Route::get('/storage/file/{id}/{from}/{do?}/{locale?}', 'FileController@show')->name('storage_file');
```
### FileController
Der Controller unterstützt jetzt den optionalen `locale` Parameter für `invoice`, `delivery` und `credit`:
```php
public function show($id = null, $from = null, $do = 'file', $locale = null)
```
### UserInvoice Model
Neue Methoden zur Ermittlung verfügbarer Sprachen:
```php
public function getAvailableLocales(): array // Gibt ['en', 'es'] zurück
public function hasLocale(string $locale): bool
```
### Angepasste Views
| View | Änderung |
| ------------------------------------------------ | ------------------------------------------- |
| `resources/views/admin/sales/_detail.blade.php` | Download-Buttons für lokalisierte Versionen |
| `resources/views/portal/order/_detail.blade.php` | Download-Buttons für lokalisierte Versionen |
### Darstellung im Admin
Wenn lokalisierte Versionen existieren, werden zusätzliche Buttons angezeigt:
- **DE-Button** (ausgefüllt): `<i class="fa fa-download"></i>` - Deutsches Original
- **Locale-Button** (outline): `<i class="fa fa-download"></i> ES` - Lokalisierte Version
### UserCredit Model
Neue Methoden zur Ermittlung verfügbarer Sprachen (analog zu UserInvoice):
```php
public function getAvailableLocales(): array // Gibt ['en', 'es'] zurück
public function hasLocale(string $locale): bool
```
### Angepasste Views für Gutschriften
| View/Controller | Änderung |
| -------------------------------------------------- | -------------------------------------------------------- |
| `app/Http/Controllers/PaymentCreditController.php` | Download-Buttons für lokalisierte Versionen in Datatable |
### Darstellung der Gutschriften im Admin
Die Gutschriften-Tabelle (`/admin/payments/credit`) zeigt jetzt:
- **DE-Button** (ausgefüllt): `<i class="fa fa-download"></i>` - Deutsches Original
- **Locale-Button** (outline): `<i class="fa fa-download"></i> ES` - Lokalisierte Version (wenn vorhanden)
## Zusammenfassung: Mehrsprachige Dokumente
| Dokument | PDF-Erstellung | E-Mail-Anhänge | Admin-Download | Kopie-Hinweis |
| ------------ | -------------- | -------------- | -------------- | ------------- |
| Rechnung | ✅ | ✅ | ✅ | ✅ |
| Lieferschein | ✅ | ✅ | ✅ | ✅ |
| Gutschrift | ✅ | ✅ | ✅ | ✅ |