Files
mareike/tests/Feature/TravelReasonTest.php
2026-09-07 14:17:50 +02:00

194 lines
6.8 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace Tests\Feature;
use App\Domains\Invoice\Actions\CreateInvoice\CreateInvoiceCommand;
use App\Domains\Invoice\Actions\CreateInvoice\CreateInvoiceRequest;
use App\Domains\Invoice\Actions\CreateInvoice\CreateInvoiceResponse;
use App\Enumerations\CostUnitType;
use App\Enumerations\InvoiceStatus;
use App\Enumerations\InvoiceType;
use App\Enumerations\TravelReason;
use App\Models\CostUnit;
use App\Models\Invoice;
use App\Models\Tenant;
use App\Resources\InvoiceResource;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;
/**
* Der Reisegrund ist eine Auswahl, kein Freitext mehr.
*
* Gespeichert wird der Schlüssel des Grundes -- außer bei "Anderer Grund": Der Schlüssel `other` sagt
* für sich nichts aus, deshalb steht dort der Text. Dieselbe Spalte führt damit weiter den Freitext der
* Bestandsbelege, ohne dass etwas umgeschrieben werden musste.
*/
class TravelReasonTest extends TestCase
{
use RefreshDatabase;
private Tenant $tenant;
protected function setUp(): void
{
parent::setUp();
$this->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());
}
}