option('since') ?? '2026-03-16'; $fix = $this->option('fix') ?? false; $orders = ShoppingOrder::query() ->where('mode', 'live') ->where('paid', 0) ->where('txaction', 'paid') ->where('created_at', '>=', $since) ->whereNull('deleted_at') ->whereDoesntHave('user_invoice') ->whereDoesntHave('user_sales_volume') // ->whereDoesntHave('shopping_payments', fn($q) => $q->where('clearingtype', 'vor')) ->orderBy('created_at') ->get(); $this->info("Betroffene Bestellungen seit {$since}: {$orders->count()}"); if ($orders->isEmpty()) { $this->info('Keine betroffenen Bestellungen gefunden.'); return self::SUCCESS; } // Zusammenfassung $total = $orders->sum('total'); $byPaymentFor = $orders->groupBy('payment_for')->map->count(); $this->table( ['payment_for', 'Anzahl'], $byPaymentFor->map(fn ($count, $type) => [$type, $count])->values() ); $this->info("Gesamtwert: {$total} EUR"); if (! $fix) { $this->warn('Trockenlauf! Nutze --fix um die Reparatur durchzufuehren.'); $this->newLine(); // Erste 10 anzeigen $this->table( ['ID', 'payment_for', 'total', 'txaction', 'created_at'], $orders->take(100)->map(fn ($o) => [ $o->id, $o->payment_for, $o->total, $o->txaction, $o->created_at->format('Y-m-d H:i'), ]) ); if ($orders->count() > 100) { $this->info('... und '.($orders->count() - 100).' weitere'); } return self::SUCCESS; } $send_mail = ! $this->option('no-mail'); if ($send_mail) { $this->info('Rechnungs-Mails werden versendet. Nutze --no-mail um dies zu unterdruecken.'); } else { $this->warn('Rechnungs-Mails werden NICHT versendet.'); } if (! $this->confirm("Wirklich {$orders->count()} Bestellungen reparieren?")) { return self::SUCCESS; } $success = 0; $errors = 0; $bar = $this->output->createProgressBar($orders->count()); $bar->start(); foreach ($orders as $order) { try { // 1. SalesVolume erstellen $user_sales_volume = SalesPointsVolume::User($order); // 2. Rechnung erstellen (mit Mail-Versand) $invoice_repo = new InvoiceRepository($order); $user_invoice = $invoice_repo->create([ 'invoice_send_mail' => $send_mail, ]); // 3. SalesVolume mit Rechnung verknuepfen $user_sales_volume->user_invoice_id = $user_invoice->id; $user_sales_volume->save(); // 4. Incentive tracking (falls relevant) IncentiveTracker::trackSalesVolume($user_sales_volume); $success++; $this->info("Order #{$order->id}: Reparatur erfolgreich"); } catch (\Throwable $e) { $errors++; $this->newLine(); $this->error("Order #{$order->id}: {$e->getMessage()}"); } $bar->advance(); } $bar->finish(); $this->newLine(2); $this->info("Fertig: {$success} repariert, {$errors} Fehler."); return $errors > 0 ? self::FAILURE : self::SUCCESS; } }