129 lines
4.3 KiB
PHP
129 lines
4.3 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\ShoppingOrder;
|
|
use App\Repositories\InvoiceRepository;
|
|
use App\Services\BusinessPlan\SalesPointsVolume;
|
|
use App\Services\Incentive\IncentiveTracker;
|
|
use Illuminate\Console\Command;
|
|
|
|
class RepairMissingInvoices extends Command
|
|
{
|
|
protected $signature = 'repair:missing-invoices
|
|
{--fix : Tatsaechlich reparieren (ohne Flag nur Vorschau)}
|
|
{--no-mail : Keine Rechnungs-Mails versenden}
|
|
{--since=2026-02-20 : Ab welchem Datum suchen}';
|
|
|
|
protected $description = 'Repariert fehlende Rechnungen und SalesVolumes fuer bezahlte Bestellungen (Bug: addSalesPointsVolumeUser)';
|
|
|
|
public function handle(): int
|
|
{
|
|
$since = $this->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;
|
|
}
|
|
}
|