20-02-2026
This commit is contained in:
parent
a8b395e20d
commit
a00c42e770
252 changed files with 28785 additions and 8907 deletions
412
dev/2026-02-04/user-language-preference.md
Normal file
412
dev/2026-02-04/user-language-preference.md
Normal 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 | ✅ | ✅ | ✅ | ✅ |
|
||||
Loading…
Add table
Add a link
Reference in a new issue