'DE'], [ 'phone' => '49', 'en' => 'Germany', 'de' => 'Deutschland', 'es' => 'Alemania', 'fr' => 'Allemagne', 'it' => 'Germania', 'ru' => 'Германия', ] ); $shoppingUserId = DB::table('shopping_users')->insertGetId([ 'auth_user_id' => 0, 'member_id' => 0, 'billing_firstname' => 'Erika', 'billing_lastname' => 'Mustermann', 'billing_email' => 'erika-'.uniqid('', true).'@example.com', 'billing_country_id' => $country->id, 'shipping_country_id' => $country->id, 'wp_order_number' => 0, 'created_at' => now(), 'updated_at' => now(), ]); $order = ShoppingOrder::forceCreate([ 'shopping_user_id' => $shoppingUserId, 'auth_user_id' => 0, 'member_id' => 0, 'country_id' => $country->id, 'user_shop_id' => 1, 'total' => 119.00, 'total_shipping' => 119.00, 'tax_split' => ['19' => '19.00'], 'net_split' => ['19' => '100.00'], ]); $original = UserInvoice::forceCreate([ 'shopping_order_id' => $order->id, 'date' => $invoiceDate, 'month' => (int) date('n', strtotime($invoiceDate)), 'year' => (int) date('Y', strtotime($invoiceDate)), 'full_number' => '202699001', 'number' => 99001, 'status' => 2, ]); $storno = UserInvoice::forceCreate([ 'shopping_order_id' => $order->id, 'date' => $cancellationDate, 'month' => (int) date('n', strtotime($cancellationDate)), 'year' => (int) date('Y', strtotime($cancellationDate)), 'full_number' => '202699002', 'number' => 99002, 'status' => 12, 'cancellation' => true, ]); $original->cancellation = true; $original->cancellation_id = $storno->id; $original->cancellation_date = $cancellationDate; $original->save(); return ['original' => $original, 'storno' => $storno]; } it('buys the revenue in the invoice month and reverses it in the cancellation month', function () { makeCancelledInvoicePair('2026-08-15', '2026-09-03'); $service = new DatevExportService; $august = $service->collectInvoiceLines(8, 2026) ->concat($service->collectCancellationLines(8, 2026)); expect($august)->toHaveCount(1); expect($august->first()['soll_haben'])->toBe('H'); expect($august->first()['belegfeld1'])->toBe('202699001'); expect(round($august->first()['amount_gross'], 2))->toBe(119.00); $september = $service->collectInvoiceLines(9, 2026) ->concat($service->collectCancellationLines(9, 2026)); expect($september)->toHaveCount(1); expect($september->first()['soll_haben'])->toBe('S'); expect($september->first()['belegfeld1'])->toBe('202699002'); expect(round($september->first()['amount_gross'], 2))->toBe(119.00); }); it('nets a same-month cancellation to zero instead of booking it twice', function () { makeCancelledInvoicePair('2026-08-15', '2026-08-20'); $service = new DatevExportService; $lines = $service->collectInvoiceLines(8, 2026) ->concat($service->collectCancellationLines(8, 2026)); expect($lines)->toHaveCount(2); $signed = $lines->sum(fn (array $line) => $line['soll_haben'] === 'S' ? -$line['amount_gross'] : $line['amount_gross']); expect(round($signed, 2))->toBe(0.00); }); it('does not treat the cancelled original invoice as a cancellation document', function () { makeCancelledInvoicePair('2026-08-15', '2026-08-20'); $cancellationLines = (new DatevExportService)->collectCancellationLines(8, 2026); expect($cancellationLines)->toHaveCount(1); expect($cancellationLines->first()['belegfeld1'])->toBe('202699002'); });