makeShopEnv()); /** * @return array{0: ShoppingOrder, 1: UserInvoice, 2: UserInvoice} Bestellung, Originalrechnung, Stornorechnung */ function makeCancelledOrderWithStornoInvoice(): array { $shoppingUser = ShoppingUser::forceCreate([ 'auth_user_id' => 0, 'billing_firstname' => 'Max', 'billing_lastname' => 'Mustermann', 'billing_email' => 'storno@example.com', 'billing_country_id' => 1, 'shipping_country_id' => 1, 'wp_order_number' => 0, 'language' => 'de', ]); $order = ShoppingOrder::create([ 'shopping_user_id' => $shoppingUser->id, 'auth_user_id' => 0, 'country_id' => 1, 'user_shop_id' => 0, 'payment_for' => 6, 'shipping' => 0, 'shipping_net' => 0, 'subtotal_ws' => 50, 'subtotal' => 50, 'tax' => 0, 'total_shipping' => 50, 'points' => 0, 'txaction' => 'cancelled', ]); $product = makeProduct(['12'], 50, 0); $order->shopping_order_items()->create([ 'product_id' => $product->id, 'is_abo_addon' => false, 'qty' => 1, 'price' => 50, 'price_net' => 50, 'tax_rate' => 0, 'tax' => 0, 'price_vk_net' => 50, 'discount' => 0, 'points' => 0, ]); $original = UserInvoice::create([ 'shopping_order_id' => $order->id, 'year' => 2026, 'month' => 7, 'date' => '2026-07-02', 'full_number' => '202600001', 'number' => 1, 'filename' => '202600001-MIVITA-Rechnung.pdf', 'dir' => 'invoice/2026/07/', 'delivery_filename' => '202600001-MIVITA-Lieferschein.pdf', 'delivery_dir' => 'delivery/2026/07/', 'disk' => 'public', 'status' => 1, ]); $storno = UserInvoice::create([ 'shopping_order_id' => $order->id, 'year' => 2026, 'month' => 7, 'date' => '2026-07-13', 'full_number' => '202600002', 'number' => 2, 'filename' => '202600002-MIVITA-Stornorechnung.pdf', 'dir' => 'invoice/2026/07/', 'delivery_filename' => '202600002-MIVITA-Storno-Lieferschein.pdf', 'delivery_dir' => 'delivery/2026/07/', 'disk' => 'public', 'cancellation' => true, 'status' => 11, ]); $original->update([ 'cancellation' => true, 'cancellation_id' => $storno->id, 'cancellation_date' => '2026-07-13', ]); return [$order, $original, $storno]; } it('lehnt eine unbekannte Stornorechnung ab', function () { $this->artisan('sales:regenerate-cancellation-pdf', ['invoices' => [999999], '--force' => true]) ->expectsOutputToContain('nicht gefunden') ->assertExitCode(1); }); it('lehnt eine Originalrechnung ab, die keine Stornorechnung ist', function () { [, $original] = makeCancelledOrderWithStornoInvoice(); $this->artisan('sales:regenerate-cancellation-pdf', ['invoices' => [$original->id], '--force' => true]) ->expectsOutputToContain('keine Stornorechnung') ->assertExitCode(1); }); it('lehnt eine Bestellung ohne Stornorechnung ab', function () { [$order, $original, $storno] = makeCancelledOrderWithStornoInvoice(); $original->update(['cancellation' => false, 'cancellation_id' => null]); $storno->delete(); $this->artisan('sales:regenerate-cancellation-pdf', ['invoices' => [$order->id], '--order' => true, '--force' => true]) ->expectsOutputToContain('hat keine Stornorechnung') ->assertExitCode(1); }); it('erzeugt die Storno-PDFs unter den bestehenden Pfaden neu, ohne neue Rechnungen anzulegen', function () { Storage::fake('public'); [, , $storno] = makeCancelledOrderWithStornoInvoice(); $this->artisan('sales:regenerate-cancellation-pdf', ['invoices' => [$storno->id], '--force' => true]) ->assertExitCode(0); // Keine neuen Rechnungen, keine Nummern verbraucht. expect(UserInvoice::count())->toBe(2); expect($storno->fresh()->full_number)->toBe('202600002'); Storage::disk('public')->assertExists('invoice/2026/07/202600002-MIVITA-Stornorechnung.pdf'); Storage::disk('public')->assertExists('delivery/2026/07/202600002-MIVITA-Storno-Lieferschein.pdf'); }); it('findet die Stornorechnung auch über die Bestell-ID', function () { Storage::fake('public'); [$order] = makeCancelledOrderWithStornoInvoice(); $this->artisan('sales:regenerate-cancellation-pdf', ['invoices' => [$order->id], '--order' => true, '--force' => true]) ->assertExitCode(0); Storage::disk('public')->assertExists('invoice/2026/07/202600002-MIVITA-Stornorechnung.pdf'); });