Rechnung/Lieferschein: - PDF-Gruppierung Abo- vs. Einmal-Artikel (is_abo_addon), rueckwaertskompatibel - Vorschau-Command sales:preview-invoice (umgeht Test-System-Gate, ohne Rechnungsnummer) Reminder-Mail (vorbereitet, Cron inaktiv): - MailAboExecutionReminder + Template, abo:send-execution-reminder, Spalte onetime_reminder_sent_for - Berater -> Sales Center, Kunde -> Portal; Vorschau abo:preview-reminder - Datum-Fix: formatDateDB() statt formatDate() (ICU-Format) Sperrfristen konfigurierbar (Admin-Settings): - abo-lock-days-change (Liefertag + Abo-Produkte), abo-lock-days-pause-cancel - Meldungen mit :lock-Platzhalter; Pausieren/Kuendigen vom Change-Lock entkoppelt - Abo-Produkt-Aenderungen im Lock-Fenster server- + clientseitig eingefroren - Selbstbedienung: Add-only/Lock nach $view (kein Admin-Bypass), Stale-Cache-Fix beim Mengen-Update Dashboard: - Einmalprodukte-Card + Team-Abo-KPI-Card, News-Card responsiv (col-xl-6) Lokalisierung: - Sprachdateien en/es/fr vollstaendig mit de synchronisiert (inkl. marketingplan/portal) - LocalizationSyncTest sichert Key-Gleichheit ab Tests: AboOneTimeInvoiceGrouping, AboExecutionReminder, AboLockDaysSetting, AboOnetimeDashboardAndMail, PreviewInvoiceCommand, TeamAboOverview + erweiterte View-Tests Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
53 lines
1.9 KiB
PHP
53 lines
1.9 KiB
PHP
<?php
|
||
|
||
namespace App\Console\Commands;
|
||
|
||
use App\Models\ShoppingOrder;
|
||
use App\Repositories\InvoiceRepository;
|
||
use Illuminate\Console\Command;
|
||
use Illuminate\Support\Facades\Storage;
|
||
|
||
class PreviewInvoice extends Command
|
||
{
|
||
/**
|
||
* Erzeugt eine Vorschau der Rechnungs-/Lieferschein-PDFs einer Bestellung,
|
||
* ohne eine offizielle Rechnung anzulegen (keine Rechnungsnummer, kein Tracking).
|
||
* Nützlich auf Testsystemen, wo die reguläre Rechnungserzeugung deaktiviert ist.
|
||
*/
|
||
protected $signature = 'sales:preview-invoice {order : ShoppingOrder-ID}';
|
||
|
||
protected $description = 'Vorschau-PDFs (Rechnung + Lieferschein) einer Bestellung erzeugen – ohne offizielle Rechnung';
|
||
|
||
public function handle(): int
|
||
{
|
||
$orderId = (int) $this->argument('order');
|
||
$order = ShoppingOrder::with('shopping_order_items.product')->find($orderId);
|
||
|
||
if (! $order) {
|
||
$this->error("ShoppingOrder {$orderId} nicht gefunden.");
|
||
|
||
return self::FAILURE;
|
||
}
|
||
|
||
try {
|
||
$paths = (new InvoiceRepository($order))->makePreview();
|
||
} catch (\Throwable $e) {
|
||
$this->error('Fehler bei der Vorschau-Erzeugung: '.$e->getMessage());
|
||
|
||
return self::FAILURE;
|
||
}
|
||
|
||
$this->info("Vorschau für Bestellung {$orderId} erzeugt (keine offizielle Rechnung, keine Nummer verbraucht):");
|
||
foreach ($paths as $type => $path) {
|
||
$label = $type === 'invoice' ? 'Rechnung ' : 'Lieferschein';
|
||
$url = preg_replace('#(?<!:)//+#', '/', Storage::disk('public')->url($path));
|
||
$this->line(" {$label}: ".$url);
|
||
$this->line(" {$label} (Datei): ".Storage::disk('public')->path($path));
|
||
}
|
||
|
||
$this->newLine();
|
||
$this->comment('Hinweis: Der Umsatzpunkte-Block entfällt in der Vorschau (kein Tracking).');
|
||
|
||
return self::SUCCESS;
|
||
}
|
||
}
|