isConfigured()) { $this->error('STRIPE_SECRET ist nicht gesetzt.'); return self::FAILURE; } $from = $this->option('from') ?: self::GO_LIVE_DATE; $to = $this->option('to'); $dryRun = (bool) $this->option('dry-run'); $limit = (int) $this->option('limit'); $query = ShoppingPayment::where('payment_provider', 'stripe') ->where('external_reference', 'LIKE', 'pi\_%') ->where('created_at', '>=', $from.' 00:00:00') ->whereHas('shopping_order.user_invoice') ->with('shopping_order.user_invoice') ->orderBy('id'); if ($to) { $query->where('created_at', '<=', $to.' 23:59:59'); } $total = $query->count(); $this->info(sprintf('%d Stripe-Zahlungen mit Rechnung ab %s gefunden.', $total, $from)); $synced = 0; $skipped = 0; $failed = 0; $query->chunkById(50, function ($payments) use (&$synced, &$skipped, &$failed, $service, $dryRun, $limit): bool { foreach ($payments as $payment) { $invoice = $payment->shopping_order?->user_invoice; if (! $invoice) { $skipped++; continue; } $this->line(sprintf( 'Zahlung #%-7d %s → Rechnung %s', $payment->id, $payment->external_reference, $invoice->full_number, )); if ($dryRun) { $synced++; } else { try { $service->sync($payment, $invoice) ? $synced++ : $skipped++; } catch (\Throwable $e) { $failed++; $this->error(' → '.$e->getMessage()); } } if ($limit > 0 && ($synced + $skipped + $failed) >= $limit) { return false; } } return true; }); $this->info(sprintf( '%s: %d übertragen, %d übersprungen (schon gesetzt / keine Rechnung), %d fehlgeschlagen.', $dryRun ? 'Probelauf' : 'Fertig', $synced, $skipped, $failed, )); return $failed > 0 ? self::FAILURE : self::SUCCESS; } }