fix: added upload formular, reorganized some files and put them into a new folder misc
This commit is contained in:
1 parent
100fe2de18
commit
0d534f5013
22 files changed
+5700
-3
No files matched your search
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Backend;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Transaction extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $connection = 'backend';
|
||||
|
||||
protected $table = 'transactions';
|
||||
|
||||
public const UPDATED_AT = 'last_modified_at';
|
||||
|
||||
public const STATUS_PENDING = 'pending';
|
||||
|
||||
public const STATUS_PROCESSING = 'processing';
|
||||
|
||||
public const STATUS_COMPLETED = 'completed';
|
||||
|
||||
public const STATUS_FAILED = 'failed';
|
||||
|
||||
protected $fillable = [
|
||||
'corporate_entity',
|
||||
'corporate_counterparty',
|
||||
'tx_date',
|
||||
'tx_amount',
|
||||
'tx_currency',
|
||||
'tx_purpose',
|
||||
'tx_country_outgoing',
|
||||
'tx_country_incoming',
|
||||
'source_file',
|
||||
'raw_payload',
|
||||
'status',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'tx_amount' => 'decimal:2',
|
||||
];
|
||||
|
||||
/**
|
||||
* KI-generierte Outputs für diese Transaktion
|
||||
*/
|
||||
public function outputs(): HasMany
|
||||
{
|
||||
return $this->hasMany(TransactionOutput::class, 'transaction_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hole spezifischen Output-Typ
|
||||
*/
|
||||
public function getOutput(string $key): ?array
|
||||
{
|
||||
return $this->outputs()
|
||||
->where('output_key', $key)
|
||||
->first()
|
||||
?->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hole alle Outputs als Key-Value Array
|
||||
*/
|
||||
public function getOutputsArray(): array
|
||||
{
|
||||
return $this->outputs()
|
||||
->get()
|
||||
->pluck('content', 'output_key')
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Company Info aus Outputs
|
||||
*/
|
||||
public function getCompanyInfo(): ?array
|
||||
{
|
||||
return $this->getOutput('company_info');
|
||||
}
|
||||
|
||||
/**
|
||||
* Risk Assessment aus Outputs
|
||||
*/
|
||||
public function getRiskAssessment(): ?array
|
||||
{
|
||||
return $this->getOutput('risk_assessment');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanctions Check aus Outputs
|
||||
*/
|
||||
public function getSanctionsCheck(): ?array
|
||||
{
|
||||
return $this->getOutput('sanctions');
|
||||
}
|
||||
|
||||
/**
|
||||
* PEP Check aus Outputs
|
||||
*/
|
||||
public function getPepCheck(): ?array
|
||||
{
|
||||
return $this->getOutput('pep');
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: Hat diese Transaction einen bestimmten Output?
|
||||
*/
|
||||
public function hasOutput(string $key): bool
|
||||
{
|
||||
return $this->outputs()->where('output_key', $key)->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ist KI-Verarbeitung abgeschlossen?
|
||||
*/
|
||||
public function isProcessed(): bool
|
||||
{
|
||||
return $this->status === self::STATUS_COMPLETED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Benötigt Review?
|
||||
*/
|
||||
public function requiresReview(): bool
|
||||
{
|
||||
$risk = $this->getRiskAssessment();
|
||||
|
||||
if (!$risk) {
|
||||
return true; // Keine Risk-Assessment → Review
|
||||
}
|
||||
|
||||
return ($risk['score'] ?? 0) >= 70 || ($risk['requires_review'] ?? false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get display-friendly company name
|
||||
*/
|
||||
public function getCompanyName(): string
|
||||
{
|
||||
$companyInfo = $this->getCompanyInfo();
|
||||
|
||||
return $companyInfo['name'] ?? $this->corporate_entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get risk score (0-100)
|
||||
*/
|
||||
public function getRiskScore(): int
|
||||
{
|
||||
$risk = $this->getRiskAssessment();
|
||||
|
||||
return $risk['score'] ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get risk level (low, medium, high)
|
||||
*/
|
||||
public function getRiskLevel(): string
|
||||
{
|
||||
$risk = $this->getRiskAssessment();
|
||||
|
||||
return $risk['level'] ?? 'unknown';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Backend;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class TransactionOutput extends Model
|
||||
{
|
||||
protected $connection = 'backend';
|
||||
|
||||
protected $table = 'transaction_outputs';
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = [
|
||||
'transaction_id',
|
||||
'prompt_id',
|
||||
'output_key',
|
||||
'content',
|
||||
'run_id',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'content' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* Transaction zu der dieser Output gehört
|
||||
*/
|
||||
public function transaction(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Transaction::class, 'transaction_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Output-Key Konstanten für Type Safety
|
||||
*/
|
||||
public const KEY_COMPANY_INFO = 'company_info';
|
||||
|
||||
public const KEY_RISK_ASSESSMENT = 'risk_assessment';
|
||||
|
||||
public const KEY_SANCTIONS = 'sanctions';
|
||||
|
||||
public const KEY_PEP = 'pep';
|
||||
|
||||
public const KEY_REGISTRY = 'registry';
|
||||
|
||||
public const KEY_GLEIF = 'gleif';
|
||||
|
||||
public const KEY_INSOLVENCY = 'insolvency';
|
||||
|
||||
public const KEY_BUNDESANZEIGER = 'bundesanzeiger';
|
||||
|
||||
public const KEY_RSS = 'rss';
|
||||
|
||||
public const KEY_EU_SANCTIONS = 'eu_sanctions';
|
||||
|
||||
public const KEY_HANDELSREGISTER = 'handelsregister';
|
||||
|
||||
public const KEY_GENESIS = 'genesis';
|
||||
|
||||
public const KEY_GOVDATA = 'govdata';
|
||||
|
||||
/**
|
||||
* Alle verfügbaren Output-Keys
|
||||
*/
|
||||
public static function availableKeys(): array
|
||||
{
|
||||
return [
|
||||
self::KEY_COMPANY_INFO,
|
||||
self::KEY_RISK_ASSESSMENT,
|
||||
self::KEY_SANCTIONS,
|
||||
self::KEY_PEP,
|
||||
self::KEY_REGISTRY,
|
||||
self::KEY_GLEIF,
|
||||
self::KEY_INSOLVENCY,
|
||||
self::KEY_BUNDESANZEIGER,
|
||||
self::KEY_RSS,
|
||||
self::KEY_EU_SANCTIONS,
|
||||
self::KEY_HANDELSREGISTER,
|
||||
self::KEY_GENESIS,
|
||||
self::KEY_GOVDATA,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get human-readable label for output key
|
||||
*/
|
||||
public static function getKeyLabel(string $key): string
|
||||
{
|
||||
return match ($key) {
|
||||
self::KEY_COMPANY_INFO => 'Company Information',
|
||||
self::KEY_RISK_ASSESSMENT => 'Risk Assessment',
|
||||
self::KEY_SANCTIONS => 'Sanctions Check',
|
||||
self::KEY_PEP => 'PEP Check',
|
||||
self::KEY_REGISTRY => 'Registry Data',
|
||||
self::KEY_GLEIF => 'GLEIF Data',
|
||||
self::KEY_INSOLVENCY => 'Insolvency Check',
|
||||
self::KEY_BUNDESANZEIGER => 'Bundesanzeiger',
|
||||
self::KEY_RSS => 'RSS Alerts',
|
||||
self::KEY_EU_SANCTIONS => 'EU Sanctions',
|
||||
self::KEY_HANDELSREGISTER => 'Handelsregister',
|
||||
self::KEY_GENESIS => 'Genesis Data',
|
||||
self::KEY_GOVDATA => 'GovData',
|
||||
default => ucfirst(str_replace('_', ' ', $key)),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Models\Backend\Transaction;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class TransactionRepository
|
||||
{
|
||||
/**
|
||||
* Alle Transaktionen mit Outputs
|
||||
*/
|
||||
public function all(): Collection
|
||||
{
|
||||
return Transaction::with('outputs')
|
||||
->orderBy('created_at', 'desc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finde Transaction by ID mit Outputs
|
||||
*/
|
||||
public function find(int $id): ?Transaction
|
||||
{
|
||||
return Transaction::with('outputs')->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transaktionen die Review benötigen
|
||||
*/
|
||||
public function requiresReview(): Collection
|
||||
{
|
||||
return Transaction::with('outputs')
|
||||
->where('status', Transaction::STATUS_COMPLETED)
|
||||
->get()
|
||||
->filter(fn ($t) => $t->requiresReview());
|
||||
}
|
||||
|
||||
/**
|
||||
* High-Risk Transaktionen
|
||||
*/
|
||||
public function highRisk(int $threshold = 70): Collection
|
||||
{
|
||||
return $this->all()
|
||||
->filter(function ($transaction) use ($threshold) {
|
||||
$risk = $transaction->getRiskAssessment();
|
||||
|
||||
return ($risk['score'] ?? 0) >= $threshold;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Transaktionen nach Firma
|
||||
*/
|
||||
public function byCompany(string $companyName): Collection
|
||||
{
|
||||
return Transaction::with('outputs')
|
||||
->where('corporate_entity', 'ILIKE', "%{$companyName}%")
|
||||
->orderBy('tx_date', 'desc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transaktionen nach Status
|
||||
*/
|
||||
public function byStatus(string $status): Collection
|
||||
{
|
||||
return Transaction::with('outputs')
|
||||
->where('status', $status)
|
||||
->orderBy('created_at', 'desc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pending Transaktionen (warten auf KI-Verarbeitung)
|
||||
*/
|
||||
public function pending(): Collection
|
||||
{
|
||||
return $this->byStatus(Transaction::STATUS_PENDING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processing Transaktionen (werden gerade verarbeitet)
|
||||
*/
|
||||
public function processing(): Collection
|
||||
{
|
||||
return $this->byStatus(Transaction::STATUS_PROCESSING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Completed Transaktionen
|
||||
*/
|
||||
public function completed(): Collection
|
||||
{
|
||||
return $this->byStatus(Transaction::STATUS_COMPLETED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Failed Transaktionen
|
||||
*/
|
||||
public function failed(): Collection
|
||||
{
|
||||
return $this->byStatus(Transaction::STATUS_FAILED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Statistiken
|
||||
*/
|
||||
public function stats(): array
|
||||
{
|
||||
$total = Transaction::count();
|
||||
$pending = Transaction::where('status', Transaction::STATUS_PENDING)->count();
|
||||
$processing = Transaction::where('status', Transaction::STATUS_PROCESSING)->count();
|
||||
$completed = Transaction::where('status', Transaction::STATUS_COMPLETED)->count();
|
||||
$failed = Transaction::where('status', Transaction::STATUS_FAILED)->count();
|
||||
|
||||
// Review Statistics
|
||||
$needsReview = $this->completed()
|
||||
->filter(fn ($t) => $t->requiresReview())
|
||||
->count();
|
||||
|
||||
// Risk Statistics
|
||||
$highRisk = $this->completed()
|
||||
->filter(fn ($t) => $t->getRiskScore() >= 70)
|
||||
->count();
|
||||
|
||||
$mediumRisk = $this->completed()
|
||||
->filter(fn ($t) => $t->getRiskScore() >= 40 && $t->getRiskScore() < 70)
|
||||
->count();
|
||||
|
||||
$lowRisk = $this->completed()
|
||||
->filter(fn ($t) => $t->getRiskScore() < 40)
|
||||
->count();
|
||||
|
||||
return compact(
|
||||
'total',
|
||||
'pending',
|
||||
'processing',
|
||||
'completed',
|
||||
'failed',
|
||||
'needsReview',
|
||||
'highRisk',
|
||||
'mediumRisk',
|
||||
'lowRisk'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paginierte Transaktionen
|
||||
*/
|
||||
public function paginated(int $perPage = 20)
|
||||
{
|
||||
return Transaction::with('outputs')
|
||||
->orderBy('created_at', 'desc')
|
||||
->paginate($perPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Suche in Transaktionen
|
||||
*/
|
||||
public function search(string $query): Collection
|
||||
{
|
||||
return Transaction::with('outputs')
|
||||
->where(function ($q) use ($query) {
|
||||
$q->where('corporate_entity', 'ILIKE', "%{$query}%")
|
||||
->orWhere('corporate_counterparty', 'ILIKE', "%{$query}%")
|
||||
->orWhere('tx_purpose', 'ILIKE', "%{$query}%");
|
||||
})
|
||||
->orderBy('created_at', 'desc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transaktionen nach Datum-Range
|
||||
*/
|
||||
public function byDateRange(string $startDate, string $endDate): Collection
|
||||
{
|
||||
return Transaction::with('outputs')
|
||||
->whereBetween('tx_date', [$startDate, $endDate])
|
||||
->orderBy('tx_date', 'desc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Alle unique Firmen
|
||||
*/
|
||||
public function getAllCompanies(): Collection
|
||||
{
|
||||
return DB::connection('backend')
|
||||
->table('transactions')
|
||||
->select('corporate_entity')
|
||||
->distinct()
|
||||
->orderBy('corporate_entity')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboard-Daten
|
||||
*/
|
||||
public function dashboardData(): array
|
||||
{
|
||||
$stats = $this->stats();
|
||||
|
||||
$recentTransactions = Transaction::with('outputs')
|
||||
->orderBy('created_at', 'desc')
|
||||
->limit(10)
|
||||
->get();
|
||||
|
||||
$recentHighRisk = $this->completed()
|
||||
->filter(fn ($t) => $t->getRiskScore() >= 70)
|
||||
->take(5);
|
||||
|
||||
$topCompanies = DB::connection('backend')
|
||||
->table('transactions')
|
||||
->select('corporate_entity', DB::raw('COUNT(*) as count'))
|
||||
->groupBy('corporate_entity')
|
||||
->orderByDesc('count')
|
||||
->limit(10)
|
||||
->get();
|
||||
|
||||
return [
|
||||
'stats' => $stats,
|
||||
'recent_transactions' => $recentTransactions,
|
||||
'recent_high_risk' => $recentHighRisk,
|
||||
'top_companies' => $topCompanies,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user