*/ protected $guarded = []; /** * Cached JSONB column casts to avoid repeated schema queries */ private static ?array $jsonbCasts = null; /** * Get the attributes that should be cast. * * Dynamically casts all JSONB columns (102 output_keys) as arrays * Uses static caching to avoid repeated database schema queries * * @return array */ protected function casts(): array { // Return cached casts if available if (self::$jsonbCasts !== null) { return self::$jsonbCasts; } $standardCasts = [ 'executed_at' => 'datetime', 'requires_review' => 'boolean', 'signals' => 'array', ]; // Standard non-JSONB columns $standardColumns = [ 'id', 'company_id', 'reference', 'amount', 'currency', 'counterparty', 'counterparty_country', 'channel', 'executed_at', 'risk_score', 'status', 'requires_review', 'flagged_by', 'flagged_reason', 'signals', 'created_at', 'updated_at', ]; try { // Get all columns from the database (only once per request) $allColumns = \Illuminate\Support\Facades\Schema::getColumnListing('transactions'); // All remaining columns are JSONB columns that should be cast as arrays $jsonbColumns = array_diff($allColumns, $standardColumns); foreach ($jsonbColumns as $column) { $standardCasts[$column] = 'array'; } } catch (\Exception $e) { // If schema query fails (e.g., during migrations), just use standard casts \Illuminate\Support\Facades\Log::warning('Failed to load JSONB column casts: ' . $e->getMessage()); } // Cache for subsequent calls self::$jsonbCasts = $standardCasts; return self::$jsonbCasts; } public function company(): BelongsTo { return $this->belongsTo(Company::class); } public function statusLabel(): string { return match ($this->status) { self::STATUS_TRUE_POSITIVE => __('Kritisches Risiko'), self::STATUS_FALSE_POSITIVE => __('Hohes Risiko'), self::STATUS_CLEARED => __('Geringes Risiko'), default => __('Unbekanntes Risiko'), }; } }