Files
AFC-Demo/misc/IMPLEMENTATION_SUMMARY.md
T

10 KiB

Implementation Summary: Backend Schema Integration

Was wurde implementiert

1. Database Configuration

Datei: config/database.php

Zwei Verbindungen hinzugefügt:

  • pgsql → public Schema (Default)
  • backend → backend Schema (search_path: 'backend')
'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

Eigenschaften:

  • Connection: backend
  • Table: transactions
  • 14 Felder (Rohdaten aus CSV Upload)

Relationships:

  • outputs() - HasMany zu TransactionOutput

Helper Methods:

// 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

Eigenschaften:

  • Connection: backend
  • Table: transaction_outputs
  • 5 Felder (KI-generierte Outputs)

Relationships:

  • transaction() - BelongsTo Transaction

Konstanten (Output-Keys):

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:

availableKeys(): array
getKeyLabel(string $key): string

3. Repository Layer

Datei: app/Repositories/TransactionRepository.php

Methoden:

// 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

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:

// 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:

// 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
// 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

// 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)

// 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:
find resources/views/livewire -type f -name "*.php" -exec sed -i '' 's/use App\\Models\\Transaction/use App\\Models\\Backend\\Transaction/g' {} +
  1. Alle use App\Models\Company entfernen:
find resources/views/livewire -type f -name "*.php" -exec sed -i '' 's/use App\\Models\\Company;//g' {} +
  1. 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:

// Alt
$transaction->sanctions_data // JSON

// Neu
$transaction->getOutput('sanctions') // Array

⚠️ Breaking Changes

1. Timestamps sind Text

// 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

// Alt
$transaction->company->name
$transaction->company()->where(...)

// Neu
$transaction->getCompanyName()
$transaction->getCompanyInfo()['name']
// Kein Relationship mehr verfügbar

3. Feld-Namen ändern sich

// Alt → Neu
amount  tx_amount
counterparty  corporate_counterparty
executed_at  tx_date

Empfehlung: Accessor in Model für Backward-Compatibility:

// 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\TransactionApp\Models\Backend\Transaction
  • Import App\Models\Company entfernen
  • Repository injecten statt direkte Model-Queries
  • company-> zu getCompanyInfo() ändern
  • Field-Namen anpassen (amounttx_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?