# Implementation Summary: Backend Schema Integration ## ✅ Was wurde implementiert ### 1. Database Configuration **Datei**: [config/database.php](config/database.php) Zwei Verbindungen hinzugefügt: - `pgsql` → public Schema (Default) - `backend` → backend Schema (search_path: 'backend') ```php 'default' => env('DB_CONNECTION', 'pgsql'), // Geändert von sqlite zu pgsql 'pgsql' => [ 'search_path' => 'public', ], 'backend' => [ 'search_path' => 'backend', // Zugriff auf backend Schema ], ``` ### 2. Backend Models #### Backend\Transaction Model **Datei**: [app/Models/Backend/Transaction.php](app/Models/Backend/Transaction.php) **Eigenschaften**: - Connection: `backend` - Table: `transactions` - 14 Felder (Rohdaten aus CSV Upload) **Relationships**: - `outputs()` - HasMany zu TransactionOutput **Helper Methods**: ```php // Outputs abrufen getOutput(string $key): ?array getOutputsArray(): array getCompanyInfo(): ?array getRiskAssessment(): ?array getSanctionsCheck(): ?array getPepCheck(): ?array // Status & Review hasOutput(string $key): bool isProcessed(): bool requiresReview(): bool // Display Helpers getCompanyName(): string getRiskScore(): int getRiskLevel(): string ``` #### Backend\TransactionOutput Model **Datei**: [app/Models/Backend/TransactionOutput.php](app/Models/Backend/TransactionOutput.php) **Eigenschaften**: - Connection: `backend` - Table: `transaction_outputs` - 5 Felder (KI-generierte Outputs) **Relationships**: - `transaction()` - BelongsTo Transaction **Konstanten** (Output-Keys): ```php KEY_COMPANY_INFO = 'company_info' KEY_RISK_ASSESSMENT = 'risk_assessment' KEY_SANCTIONS = 'sanctions' KEY_PEP = 'pep' KEY_REGISTRY = 'registry' KEY_GLEIF = 'gleif' KEY_INSOLVENCY = 'insolvency' KEY_BUNDESANZEIGER = 'bundesanzeiger' KEY_RSS = 'rss' KEY_EU_SANCTIONS = 'eu_sanctions' KEY_HANDELSREGISTER = 'handelsregister' KEY_GENESIS = 'genesis' KEY_GOVDATA = 'govdata' ``` **Helper Methods**: ```php availableKeys(): array getKeyLabel(string $key): string ``` ### 3. Repository Layer **Datei**: [app/Repositories/TransactionRepository.php](app/Repositories/TransactionRepository.php) **Methoden**: ```php // Basic CRUD all(): Collection find(int $id): ?Transaction paginated(int $perPage = 20) // Filtering requiresReview(): Collection highRisk(int $threshold = 70): Collection byCompany(string $companyName): Collection byStatus(string $status): Collection byDateRange(string $startDate, string $endDate): Collection search(string $query): Collection // Status-specific pending(): Collection processing(): Collection completed(): Collection failed(): Collection // Statistics stats(): array dashboardData(): array getAllCompanies(): Collection ``` ### 4. Tests **Datei**: [tests/Feature/BackendModelsTest.php](tests/Feature/BackendModelsTest.php) 11 Tests geschrieben (3 laufen ohne DB-Verbindung): - ✅ Connection Tests - ✅ Model Relationship Tests - ✅ Helper Method Tests - ✅ Constant Tests --- ## 📋 Nächste Schritte: Component-Migration ### Betroffene Components #### 1. transaction-review.blade.php **Aktuell**: Verwendet `App\Models\Transaction` und `App\Models\Company` **Änderungen**: ```php // Alt use App\Models\Transaction; use App\Models\Company; // Neu use App\Models\Backend\Transaction; use App\Repositories\TransactionRepository; // Repository verwenden statt direkte Model-Queries public function __construct( private TransactionRepository $transactions ) {} $transactions = $this->transactions->all(); ``` **Mapping**: | Alt (public.transactions) | Neu (backend) | |---------------------------|---------------| | `$transaction->company->name` | `$transaction->getCompanyName()` | | `$transaction->company->legal_name` | `$transaction->getCompanyInfo()['legal_name']` | | `$transaction->company->sector` | `$transaction->getCompanyInfo()['sector']` | | `$transaction->risk_score` | `$transaction->getRiskScore()` | | `$transaction->requires_review` | `$transaction->requiresReview()` | | `$transaction->amount` | `$transaction->tx_amount` | | `$transaction->counterparty` | `$transaction->corporate_counterparty` | | `$transaction->executed_at` | `$transaction->tx_date` (⚠️ ist text) | #### 2. companies/transactions.blade.php **Aktuell**: Verwendet `App\Models\Company` Parameter **Änderungen**: - Company-Daten kommen jetzt aus `transaction_outputs` - Grouping nach `corporate_entity` statt `company_id` **Neuer Ansatz**: ```php // Alle Transaktionen für eine Firma $companyName = 'Siemens AG'; // Aus Route oder Parameter $transactions = $this->transactions->byCompany($companyName); // Company-Info aus erster Transaction $companyInfo = $transactions->first()?->getCompanyInfo(); ``` #### 3. company-search.blade.php **Änderungen**: - Suche jetzt in `backend.transactions.corporate_entity` - Keine separate Company-Tabelle mehr ```php // Repository Method public function getAllCompanies(): Collection { return DB::connection('backend') ->table('transactions') ->select('corporate_entity as name') ->distinct() ->orderBy('corporate_entity') ->get(); } ``` --- ## 🔄 Migrationsplan (Step-by-Step) ### Phase 1: Testen ohne Breaking Changes (empfohlen) **Option A: Feature Flag** ```php // config/features.php 'use_backend_schema' => env('FEATURE_USE_BACKEND_SCHEMA', false), // In Components if (config('features.use_backend_schema')) { $transactions = app(TransactionRepository::class)->all(); } else { $transactions = Transaction::all(); // Alt } ``` **Option B: Neue Routes** (empfohlen für parallele Tests) ```php // routes/web.php Route::get('/beta/transactions', ...); // Nutzt Backend-Schema Route::get('/transactions', ...); // Alte Implementation ``` ### Phase 2: Direkte Migration (schneller, aber riskanter) 1. **Alle `use App\Models\Transaction` ersetzen**: ```bash find resources/views/livewire -type f -name "*.php" -exec sed -i '' 's/use App\\Models\\Transaction/use App\\Models\\Backend\\Transaction/g' {} + ``` 2. **Alle `use App\Models\Company` entfernen**: ```bash find resources/views/livewire -type f -name "*.php" -exec sed -i '' 's/use App\\Models\\Company;//g' {} + ``` 3. **Component für Component anpassen**: - transaction-review.blade.php - companies/transactions.blade.php - company-search.blade.php --- ## 🗺️ Daten-Mapping Referenz ### Transaction Fields | public.transactions | backend.transactions | Typ-Unterschied | |---------------------|----------------------|-----------------| | id | id | bigint → integer | | company_id | - (via corporate_entity) | Relationship entfällt | | reference | - | Neu: auto-generated | | amount | tx_amount | numeric → double | | currency | tx_currency | ✓ | | counterparty | corporate_counterparty | ✓ | | counterparty_country | tx_country_incoming | ✓ | | channel | - | Nicht in backend | | executed_at | tx_date | **timestamp → text!** | | risk_score | - (in outputs) | Via getRiskScore() | | status | status | ✓ | | requires_review | - (computed) | Via requiresReview() | | flagged_by | - | Nicht in backend | | flagged_reason | tx_purpose | Ähnlich | | signals | - | Nicht in backend | ### Company Fields (jetzt in transaction_outputs) | public.companies | transaction_outputs (key='company_info') | |------------------|-------------------------------------------| | name | content['name'] | | legal_name | content['legal_name'] | | ticker | content['ticker'] | | sector | content['sector'] | | country | content['country'] | | headquarters | content['headquarters'] | | kyc_risk_level | content['kyc_risk_level'] | | summary | content['summary'] | ### Enrichment Fields (in transaction_outputs) Alle 35 Enrichment-Felder aus `public.transactions` sind jetzt separate Outputs: ```php // Alt $transaction->sanctions_data // JSON // Neu $transaction->getOutput('sanctions') // Array ``` --- ## ⚠️ Breaking Changes ### 1. Timestamps sind Text ```php // Alt $transaction->executed_at->format('d.m.Y') // Neu (ACHTUNG: tx_date ist Text!) $transaction->tx_date // Already string, no format() ``` **Empfehlung**: Migration hinzufügen um `tx_date` von `text` zu `timestamp` zu ändern. ### 2. Company Relationship entfällt ```php // Alt $transaction->company->name $transaction->company()->where(...) // Neu $transaction->getCompanyName() $transaction->getCompanyInfo()['name'] // Kein Relationship mehr verfügbar ``` ### 3. Feld-Namen ändern sich ```php // Alt → Neu amount → tx_amount counterparty → corporate_counterparty executed_at → tx_date ``` **Empfehlung**: Accessor in Model für Backward-Compatibility: ```php // In Backend\Transaction Model protected $appends = ['amount', 'counterparty', 'executed_at']; public function getAmountAttribute(): float { return $this->tx_amount; } public function getCounterpartyAttribute(): string { return $this->corporate_counterparty; } public function getExecutedAtAttribute(): string { return $this->tx_date; } ``` --- ## 🎯 Empfohlenes Vorgehen ### Option 1: Schrittweise mit Feature Flags (Sicher, 2-3 Wochen) 1. ✅ Backend Models & Repository erstellt 2. ⬜ Feature Flag System einrichten 3. ⬜ Parallele Routes `/beta/*` erstellen 4. ⬜ Einen Component nach dem anderen migrieren 5. ⬜ Testen mit echten Nutzern (10%) 6. ⬜ Gradual Rollout 7. ⬜ Alte Components entfernen ### Option 2: Direkte Migration (Schnell, 3-5 Tage) 1. ✅ Backend Models & Repository erstellt 2. ⬜ Alle Components in einem PR umstellen 3. ⬜ Accessor für Backward-Compatibility hinzufügen 4. ⬜ Intensives Testing 5. ⬜ Deploy mit Rollback-Plan ### Option 3: Hybrid (Empfohlen, 1 Woche) 1. ✅ Backend Models & Repository erstellt 2. ⬜ Accessor für Backward-Compatibility in Backend Models 3. ⬜ `transaction-review` Component migrieren (wichtigster) 4. ⬜ 1-2 Tage Testing 5. ⬜ Restliche Components migrieren 6. ⬜ Deploy --- ## 📝 Checkliste für Component-Migration Für jeden Component: - [ ] Import `App\Models\Transaction` → `App\Models\Backend\Transaction` - [ ] Import `App\Models\Company` entfernen - [ ] Repository injecten statt direkte Model-Queries - [ ] `company->` zu `getCompanyInfo()` ändern - [ ] Field-Namen anpassen (`amount` → `tx_amount`, etc.) - [ ] `executed_at` zu `tx_date` ändern - [ ] `->format()` Calls bei `tx_date` entfernen (ist schon Text) - [ ] Tests schreiben/anpassen - [ ] Manuell testen - [ ] PR erstellen --- ## 🚀 Los geht's! Möchten Sie: **A)** Dass ich jetzt `transaction-review.blade.php` auf Backend-Schema umstelle? **B)** Erst Accessors für Backward-Compatibility hinzufügen? **C)** Ein Feature-Flag-System einrichten? **D)** Etwas anderes? Was ist Ihr bevorzugter Ansatz?