tenant = Tenant::create([ 'slug' => 'wm', 'name' => 'Wilde Möhre', 'address_1' => 'Musterweg 1', 'email' => 't@example.com', 'email_finance' => 'finance@example.com', 'url' => parse_url(config('app.url'), PHP_URL_HOST), 'account_name' => 'Test e.V.', 'account_iban' => 'DE00', 'account_bic' => 'XY', 'city' => 'Stadt', 'postcode' => '00000', 'invoice_prefix' => 'WM', 'is_active_local_group' => true, 'has_active_instance' => true, ]); app()->instance('tenant', $this->tenant); DB::table('cost_unit_types')->insert(['slug' => CostUnitType::COST_UNIT_TYPE_EVENT, 'name' => 'Veranstaltung']); DB::table('invoice_status')->insert(['slug' => InvoiceStatus::INVOICE_STATUS_NEW]); DB::table('invoice_types')->insert([ 'slug' => InvoiceType::INVOICE_TYPE_TRAVELLING, 'name' => 'Fahrtkosten', 'sort_order' => 1, 'selectable' => true, 'counts_as_expense' => true, ]); Mail::fake(); } private function makeCostUnit(): CostUnit { return CostUnit::create([ 'tenant' => $this->tenant->slug, 'name' => 'Sommerlager', 'type' => CostUnitType::COST_UNIT_TYPE_EVENT, 'distance_allowance' => 0.25, 'mail_on_new' => false, 'allow_new' => true, 'archived' => false, ]); } /** * Der Weg, den eine eingereichte Fahrtkostenabrechnung nimmt. `contactEmail` bleibt leer, damit kein * Bestätigungsmailversand mitläuft. */ private function submit(?string $reason, ?string $note = null, ?string $travellers = 'Mika und Kim'): CreateInvoiceResponse { return new CreateInvoiceCommand(new CreateInvoiceRequest( costUnit: $this->makeCostUnit(), contactName: 'Max Mustermann', invoiceType: InvoiceType::INVOICE_TYPE_TRAVELLING, totalAmount: 42.0, receiptFile: null, isDonation: false, travelRoute: 'Halle – Leipzig', travelReason: $reason, travelReasonNote: $note, travellers: $travellers, ))->execute(); } /* |-------------------------------------------------------------------------- | Die Auswahl |-------------------------------------------------------------------------- */ public function test_the_options_are_ordered_and_only_the_last_one_needs_a_note(): void { $options = TravelReason::options(); $this->assertSame( ['event_travel', 'material_transport', 'purchase', 'other'], array_column($options, 'value') ); $this->assertSame('An-/Abreise zur Veranstaltung', $options[0]['label']); $this->assertSame([false, false, false, true], array_column($options, 'requiresNote')); } /* |-------------------------------------------------------------------------- | Was gespeichert wird |-------------------------------------------------------------------------- */ public function test_a_fixed_reason_is_stored_as_its_key(): void { $invoice = $this->submit(TravelReason::MATERIAL_TRANSPORT)->invoice; $this->assertSame(TravelReason::MATERIAL_TRANSPORT, $invoice->travel_reason); } public function test_the_purpose_carries_the_name_not_the_key(): void { // In der Belegliste soll "Materialtransport" stehen, nicht "material_transport". $invoice = $this->submit(TravelReason::MATERIAL_TRANSPORT)->invoice; $this->assertSame('Materialtransport — Mika und Kim', $invoice->purpose); } public function test_another_reason_stores_the_text_instead_of_the_key(): void { $invoice = $this->submit(TravelReason::OTHER, 'Abholung der Ausrüstung')->invoice; $this->assertSame('Abholung der Ausrüstung', $invoice->travel_reason); $this->assertSame('Abholung der Ausrüstung — Mika und Kim', $invoice->purpose); } public function test_another_reason_without_a_text_creates_nothing(): void { // Sicherheitsnetz hinter der Oberfläche: Dort geht es ohne Erläuterung nicht weiter. $response = $this->submit(TravelReason::OTHER, ' '); $this->assertFalse($response->success); $this->assertNull($response->invoice); $this->assertSame(0, Invoice::count()); $this->assertNotNull($response->message); } public function test_an_unknown_value_passes_through_unchanged(): void { // Bestandsbelege und ihre Kopien bringen ihren Freitext schon mit. $invoice = $this->submit('Fahrt zum Landeslager')->invoice; $this->assertSame('Fahrt zum Landeslager', $invoice->travel_reason); $this->assertSame('Fahrt zum Landeslager — Mika und Kim', $invoice->purpose); } /* |-------------------------------------------------------------------------- | Was angezeigt wird |-------------------------------------------------------------------------- */ public function test_a_key_is_shown_as_its_name(): void { $invoice = $this->submit(TravelReason::EVENT_TRAVEL)->invoice; $this->assertSame('An-/Abreise zur Veranstaltung', $invoice->travelReasonText()); $this->assertSame( 'An-/Abreise zur Veranstaltung', new InvoiceResource($invoice)->toArray()['travelReason'] ); } public function test_free_text_is_shown_as_itself(): void { $invoice = $this->submit('Fahrt zum Landeslager')->invoice; $this->assertSame('Fahrt zum Landeslager', $invoice->travelReasonText()); } }