Warenwirtschaft: Review-Fix — Altdaten-PDFs zentral regenerieren (ensureFilesOnDisk)

document('combined') lief bei fehlender Alt-PDF ungeprüft in eine
PDFMerger-Exception (500); der Sammel-Druck prüfte nur den Lieferschein,
eine fehlende Rechnungs-PDF ließ den ganzen Batch platzen. Neue zentrale
InvoiceRepository::ensureFilesOnDisk() ersetzt den dreifach kopierten
Altdaten-Check (MailLogistic 2x, batchDocuments); Merge-/Response-Code im
OrderFulfillmentController zu mergedPdf()/pdfResponse() dedupliziert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-20 12:28:41 +00:00
parent 8ad0f65947
commit f28f4b4b68
5 changed files with 242 additions and 132 deletions

View file

@ -11,6 +11,7 @@ use App\Models\ShoppingOrderItem;
use App\Models\ShoppingPayment;
use App\Models\ShoppingUser;
use App\Models\UserAccount;
use App\Services\Invoice;
use App\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Mail;
@ -279,6 +280,73 @@ test('sammel-druck erzeugt fehlende dokumente und liefert ein pdf', function ()
Mail::assertNothingSent();
});
test('kombi-download regeneriert fehlende altdateien statt fehler', function () {
// Review 20.07.2026: der combined-Zweig lief bei fehlender PDF-Datei ungeprüft
// in eine PDFMerger-Exception (HTTP 500) — jetzt zentrale Altdaten-Regeneration
Mail::fake();
Storage::fake('public');
Setting::setContentBySlug('invoice-number', 3000, 'int');
$product = ofMakeProduct('OF Altdaten');
$order = ofMakeOrder([['product' => $product, 'qty' => 1]]);
$user = ofMakeUser(1);
$cwd = getcwd();
chdir(public_path());
try {
$this->actingAs($user)
->post(route('admin.inventory.orders.documents', $order->id))
->assertRedirect();
// Altdaten-Fall: Rechnungs-PDF von der Platte gelöscht, Metadaten vorhanden
$order->refresh();
Storage::disk('public')->delete(Invoice::getDownloadPath($order));
$this->actingAs($user)
->get(route('admin.inventory.orders.document', [$order->id, 'combined']))
->assertOk()
->assertHeader('Content-Type', 'application/pdf');
} finally {
chdir($cwd);
}
Storage::disk('public')->assertExists(Invoice::getDownloadPath($order));
});
test('sammel-druck regeneriert fehlende rechnungs-pdf auch bei vorhandenem lieferschein', function () {
// Review 20.07.2026: vorher prüfte der Sammel-Druck nur den Lieferschein —
// eine fehlende Rechnungs-PDF ließ den ganzen Batch mit 500 platzen
Mail::fake();
Storage::fake('public');
Setting::setContentBySlug('invoice-number', 4000, 'int');
$product = ofMakeProduct('OF Batch-Altdaten');
$order = ofMakeOrder([['product' => $product, 'qty' => 1]]);
$user = ofMakeUser(1);
$cwd = getcwd();
chdir(public_path());
try {
$this->actingAs($user)
->post(route('admin.inventory.orders.documents', $order->id))
->assertRedirect();
$order->refresh();
Storage::disk('public')->delete(Invoice::getDownloadPath($order));
Storage::disk('public')->assertExists(Invoice::getDownloadPathDelivery($order));
$this->actingAs($user)
->post(route('admin.inventory.orders.documents.batch'), [
'order_ids' => [$order->id],
'type' => 'combined',
])
->assertOk()
->assertHeader('Content-Type', 'application/pdf');
} finally {
chdir($cwd);
}
Storage::disk('public')->assertExists(Invoice::getDownloadPath($order));
});
test('sammel-druck nur mit api-bestellungen wird abgelehnt', function () {
$order = ofMakeOrder([], ['txaction' => 'extern', 'wp_invoice_path' => 'https://shop.example/invoice/2.pdf']);