# Payment Status Legende & Race Condition Fix **Datum:** 28.01.2026 **Bereich:** Payment System / Payone Integration **Status:** ✅ Abgeschlossen --- ## Übersicht Umfassende Verbesserung des Payment-Link-Systems mit folgenden Komponenten: 1. Dynamische mehrsprachige Status-Legende 2. Race Condition Fix für Payone Requests 3. Status Update für alle Bestellungstypen 4. ShoppingInstance Model Korrektur 5. Artisan Command für Datenbank-Cleanup --- ## Problem 1: Fehlende Status-Übersicht ### Ausgangslage - Benutzer sahen Payment Status-Badges in der Payment Links Übersicht - Keine Erklärung, was die verschiedenen Status/Farben bedeuten - Keine Legende zur Orientierung ### Lösung Dynamische Status-Legende oberhalb der Tabelle mit allen verfügbaren Status. --- ## Problem 2: Race Condition bei Payone Requests ### Ausgangslage Payone sendet mehrere Status-Updates für eine Zahlung: 1. `appointed` - Zahlung autorisiert 2. `paid` - Zahlung abgeschlossen **Problem:** Wenn die Requests in falscher Reihenfolge ankommen: ``` 1. paid kommt zuerst → txaction = 'paid' ✓ 2. appointed kommt später → txaction = 'appointed' ✗ (überschreibt paid!) ``` Dies führte zu: - Falschen Status in `shopping_orders.txaction` und `shopping_payments.txaction` - ShoppingInstance Status blieb teilweise auf 4 (appointed) statt 10 (paid) - Verwirrung bei Benutzern und Support ### Root Cause In `PayoneController.php` wurden die `txaction` Felder **immer** überschrieben: ```php $shopping_order->txaction = $data['txaction']; // IMMER überschrieben! $shopping_payment->txaction = $data['txaction']; // IMMER überschrieben! ``` ### Lösung Prioritätsprüfung vor dem Update: ```php $txaction_priority = [ 'appointed' => 1, 'pending' => 2, 'failed' => 3, 'paid' => 10, // höchste Priorität - finaler Status ]; // Nur updaten wenn neue Priorität höher ist if ($new_priority > $current_priority) { $shopping_order->txaction = $data['txaction']; $shopping_payment->txaction = $data['txaction']; } ``` --- ## Problem 3: Status nur für Abo-Bestellungen ### Ausgangslage In `Payment::paymentStatusPaidAction()` wurde Status 10 (`link_paid`) nur gesetzt wenn: ```php if ($shopping_order->is_abo) { Util::setInstanceStatusByPayment($shopping_payment, 10); } ``` **Resultat:** - ✅ Abo-Bestellungen: Status korrekt auf 10 - ❌ Normale Bestellungen: Status blieb auf 4 (appointed) ### Lösung Status 10 wird jetzt **immer** bei erfolgreicher Zahlung gesetzt: ```php // Set payment link status to paid for all orders if ($shopping_payment) { Util::setInstanceStatusByPayment($shopping_payment, 10); } // Abo-spezifische Logik separat if ($shopping_order->is_abo) { AboHelper::setAboActive($shopping_order, 2, true); } ``` --- ## Problem 4: ShoppingInstance Model ### Ausgangslage - Tabelle `shopping_instances` hat `identifier` (VARCHAR) als Primary Key - Laravel Model hatte keine Primary Key Konfiguration - Eloquent verwendete standardmäßig `id` (nicht existent) - `save()` schlug fehl mit: "Unknown column 'id' in 'where clause'" ### Lösung Primary Key im Model korrekt konfiguriert: ```php class ShoppingInstance extends Model { protected $primaryKey = 'identifier'; public $incrementing = false; protected $keyType = 'string'; // ... } ``` --- ## Implementierung ### 1. OrderPaymentService - Zentrale Status-Definition **Datei:** `app/Services/OrderPaymentService.php` ```php public static function getStatusBadgeClasses() { return [ 'link_sent' => 'default', 'link_openly' => 'info', 'link_paid' => 'secondary', 'link_check' => 'warning', 'link_pending' => 'warning', 'link_appointed' => 'warning', 'link_failed' => 'danger', 'link_canceled' => 'danger' ]; } public static function getStatusBadge(ShoppingInstance $shoppingInstance) { $status = $shoppingInstance->getStatus(); $badgeClasses = self::getStatusBadgeClasses(); // Nutzt zentrale Definition if (isset($badgeClasses[$status])) { return sprintf( ' %s', $badgeClasses[$status], __('payment.' . $status) ); } return ''; } ``` **Vorteile:** - ✅ Eine zentrale Stelle für Status-Definitionen - ✅ DRY Prinzip (Don't Repeat Yourself) - ✅ Leicht erweiterbar für neue Status ### 2. Payment Links View - Dynamische Legende **Datei:** `resources/views/user/order/payment/index.blade.php` ```blade {{-- Status-Legende --}}