"Vertriebspartner", 'customer_order' => "Kundenbestellung", 'user_for_customer' => "VP.Kundenbestellung", ]; // Konstanten für bessere Wartbarkeit const CREDIT_STATUS_DEDUCTION = 2; const CREDIT_STATUS_RETURN = 4; const CREDIT_STATUS_CHARGED = 7; const CREDIT_STATUS_REMOVED = 8; const TRANSACTION_REQUEST = 'transaction'; const DEFAULT_TXID = 0; const DEFAULT_USERID = 0; /** * Aktualisiert den Transaktionsstatus einer Bestellung * * @param int $orderId * @param string $txaction * @param int $paymentId * @return bool * @throws \Exception */ public static function updateTransactionStatus($orderId, $txaction, $paymentId) { // Validierung der Eingabeparameter if (empty($orderId) || empty($txaction) || empty($paymentId)) { throw new \InvalidArgumentException('Alle Parameter müssen angegeben werden'); } return DB::transaction(function () use ($orderId, $txaction, $paymentId) { $shopping_order = ShoppingOrder::findOrFail($orderId); $shopping_payment = ShoppingPayment::findOrFail($paymentId); // Prüfen ob sich der Status tatsächlich geändert hat if ($shopping_payment->txaction === $txaction) { return false; } // Guthaben-Logik für Partner-Center Bestellungen self::handlePartnerCenterCredits($shopping_order, $txaction); // PaymentTransaction erstellen $paymentTransaction = self::createPaymentTransaction($shopping_payment, $txaction); // Bestellung und Payment aktualisieren self::updateOrderAndPayment($shopping_order, $shopping_payment, $txaction, $paymentTransaction); // Paid-Action ausführen falls nötig self::handlePaidAction($paymentTransaction, $shopping_order); // Credit-Loading Logik self::handleCreditLoading($shopping_order, $txaction); // E-Mail versenden self::sendStatusEmail($shopping_order, $shopping_payment, $paymentTransaction); return true; }); } /** * Behandelt Guthaben-Logik für Partner-Center Bestellungen */ private static function handlePartnerCenterCredits(ShoppingOrder $shoppingOrder, string $txaction): void { if (!$shoppingOrder->shopping_order_margin || $shoppingOrder->shopping_order_margin->from_payment_credit <= 0) { return; } $lastUserPayCredit = self::getLastUserPayCredit($shoppingOrder->id, [self::CREDIT_STATUS_DEDUCTION, self::CREDIT_STATUS_RETURN]); if (!$lastUserPayCredit) { return; } // Status Keine Zahlung, Guthaben zurückführen if ($txaction === 'non' && $lastUserPayCredit->status === self::CREDIT_STATUS_DEDUCTION) { Payment::handelUserPayCredits($shoppingOrder, 'return'); } // Status Zahlung, vorher gab es eine Storno, Guthaben abziehen if ($lastUserPayCredit->status === self::CREDIT_STATUS_RETURN && in_array($txaction, ['open', 'paid'])) { Payment::handelUserPayCredits($shoppingOrder, 'deduction'); } } /** * Erstellt eine neue PaymentTransaction */ private static function createPaymentTransaction(ShoppingPayment $shoppingPayment, string $txaction): PaymentTransaction { return PaymentTransaction::create([ 'shopping_payment_id' => $shoppingPayment->id, 'request' => self::TRANSACTION_REQUEST, 'txid' => self::DEFAULT_TXID, 'userid' => self::DEFAULT_USERID, 'status' => $shoppingPayment->clearingtype, 'transmitted_data' => null, 'txaction' => $txaction, 'mode' => $shoppingPayment->mode, ]); } /** * Aktualisiert Bestellung und Payment */ private static function updateOrderAndPayment(ShoppingOrder $shoppingOrder, ShoppingPayment $shoppingPayment, string $txaction, PaymentTransaction $paymentTransaction): void { $shoppingOrder->txaction = $txaction; $shoppingOrder->paid = $paymentTransaction->txaction === 'paid'; $shoppingOrder->save(); $shoppingPayment->txaction = $txaction; $shoppingPayment->save(); } /** * Führt Paid-Action aus falls nötig */ private static function handlePaidAction(PaymentTransaction $paymentTransaction, ShoppingOrder $shoppingOrder): void { if ($paymentTransaction->status === 'vor' && $paymentTransaction->txaction === 'paid') { Payment::paymentStatusPaidAction($shoppingOrder, true); } } /** * Behandelt Credit-Loading Logik */ private static function handleCreditLoading(ShoppingOrder $shoppingOrder, string $txaction): void { if (!$shoppingOrder->shopping_user || $shoppingOrder->shopping_user->is_for !== 'cr') { return; } $lastUserPayCredit = self::getLastUserPayCredit($shoppingOrder->id, [self::CREDIT_STATUS_CHARGED, self::CREDIT_STATUS_REMOVED]); if (!$lastUserPayCredit) { return; } // Status Keine Zahlung, Guthaben abziehen if ($txaction === 'non' && $lastUserPayCredit->status === self::CREDIT_STATUS_CHARGED) { Payment::handelUserPayChargingCredits($shoppingOrder, 'remove'); } // Status Zahlung, vorher gab es eine Storno, Guthaben wieder aufladen if ($lastUserPayCredit->status === self::CREDIT_STATUS_REMOVED && $txaction === 'paid') { Payment::handelUserPayChargingCredits($shoppingOrder, 'add'); } } /** * Sendet Status-E-Mail */ private static function sendStatusEmail(ShoppingOrder $shoppingOrder, ShoppingPayment $shoppingPayment, PaymentTransaction $paymentTransaction): void { $emailData = [ 'mode' => $paymentTransaction->mode, 'txaction' => $paymentTransaction->txaction, 'send_link' => false, ]; try { Payment::paymentStatusSendMail($shoppingOrder, $shoppingPayment, $emailData); } catch (\Exception $e) { Log::error('Fehler beim Senden der Status-E-Mail', [ 'order_id' => $shoppingOrder->id, 'payment_id' => $shoppingPayment->id, 'error' => $e->getMessage() ]); } } /** * Holt den letzten UserPayCredit Eintrag */ private static function getLastUserPayCredit(int $orderId, array $statuses): ?UserPayCredit { return UserPayCredit::where('shopping_order_id', $orderId) ->whereIn('status', $statuses) ->orderBy('id', 'DESC') ->first(); } }