Zahlungszwecke
This commit is contained in:
@@ -260,7 +260,26 @@ class EventIncomeSurplusStatementTest extends TestCase
|
||||
typeOther: 'Bastelmaterial'
|
||||
);
|
||||
|
||||
$this->assertSame('Bastelmaterial — Materialkauf', $this->group('Programmkosten')['rows'][0]['purpose']);
|
||||
$this->assertSame('Bastelmaterial', $this->group('Programmkosten')['rows'][0]['purpose']);
|
||||
}
|
||||
|
||||
public function test_a_recorded_purpose_wins(): void
|
||||
{
|
||||
// Der Regelfall für neue Belege: Der Zahlungsgrund wird beim Einreichen erfasst und steht in
|
||||
// seiner eigenen Spalte -- korrigierbar, ohne dass ihn etwas wieder überschreibt.
|
||||
$this->makeEvent();
|
||||
$this->makeInvoice(
|
||||
InvoiceType::INVOICE_TYPE_PROGRAM,
|
||||
100.0,
|
||||
InvoiceStatus::INVOICE_STATUS_EXPORTED,
|
||||
typeOther: 'Bastelmaterial',
|
||||
purpose: 'Material für den Bastelnachmittag'
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
'Material für den Bastelnachmittag',
|
||||
$this->group('Programmkosten')['rows'][0]['purpose']
|
||||
);
|
||||
}
|
||||
|
||||
public function test_travel_costs_name_the_reason_and_who_travelled(): void
|
||||
@@ -286,16 +305,18 @@ class EventIncomeSurplusStatementTest extends TestCase
|
||||
travelReason: 'Landeslager'
|
||||
);
|
||||
|
||||
$this->assertSame('Landeslager — Mika Muster — Materialkauf', $this->group('Fahrtkosten')['rows'][0]['purpose']);
|
||||
$this->assertSame('Landeslager — Mika Muster', $this->group('Fahrtkosten')['rows'][0]['purpose']);
|
||||
}
|
||||
|
||||
public function test_an_older_receipt_without_the_purchase_note_falls_back_to_the_comment(): void
|
||||
public function test_the_comment_is_no_longer_part_of_the_purpose(): void
|
||||
{
|
||||
// Belege von vor der Pflichtangabe haben `type_other` leer.
|
||||
// Die Anmerkung trägt, was die Kassenwart*in beim Korrigieren notiert hat -- sie steht auf dem
|
||||
// Beleg-PDF und hat im Zweck nichts zu suchen. Bestandsbelege ohne erfassten Zahlungsgrund haben
|
||||
// hier deshalb eine leere Zelle; nachtragen lässt er sich beim Korrigieren.
|
||||
$this->makeEvent();
|
||||
$this->makeInvoice(InvoiceType::INVOICE_TYPE_PROGRAM, 100.0, InvoiceStatus::INVOICE_STATUS_NEW);
|
||||
|
||||
$this->assertSame('Materialkauf', $this->group('Programmkosten')['rows'][0]['purpose']);
|
||||
$this->assertSame('', $this->group('Programmkosten')['rows'][0]['purpose']);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -498,7 +519,8 @@ class EventIncomeSurplusStatementTest extends TestCase
|
||||
string $status,
|
||||
bool $donation = false,
|
||||
?string $typeOther = null,
|
||||
?string $travelReason = null
|
||||
?string $travelReason = null,
|
||||
?string $purpose = null
|
||||
): Invoice {
|
||||
return Invoice::create([
|
||||
'tenant' => $this->tenant->slug,
|
||||
@@ -507,6 +529,7 @@ class EventIncomeSurplusStatementTest extends TestCase
|
||||
'status' => $status,
|
||||
'type' => $type,
|
||||
'type_other' => $typeOther,
|
||||
'purpose' => $purpose,
|
||||
'travel_reason' => $travelReason,
|
||||
'donation' => $donation,
|
||||
'contact_name' => 'Mika Muster',
|
||||
|
||||
@@ -2,20 +2,30 @@
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Domains\Invoice\Actions\CreateInvoice\CreateInvoiceCommand;
|
||||
use App\Domains\Invoice\Actions\CreateInvoice\CreateInvoiceRequest;
|
||||
use App\Domains\Invoice\Actions\UpdateInvoice\UpdateInvoiceCommand;
|
||||
use App\Domains\Invoice\Actions\UpdateInvoice\UpdateInvoiceRequest;
|
||||
use App\Enumerations\CostUnitType;
|
||||
use App\Enumerations\InvoiceStatus;
|
||||
use App\Enumerations\InvoiceType;
|
||||
use App\Enumerations\UserRole;
|
||||
use App\Models\CostUnit;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Tenant;
|
||||
use App\Models\User;
|
||||
use App\Resources\InvoiceResource;
|
||||
use App\ValueObjects\Amount;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Die Spalte "Zahlungsgrund" der Beleglisten. Sie liest nicht ein Feld, sondern das, was der
|
||||
* Einreiche-Flow je Abrechnungstyp gefüllt hat -- bei Fahrtkosten ist `type_other` leer.
|
||||
* Der Zahlungsgrund: die gleichnamige Spalte der Beleglisten und der "Zweck" der EüR-Anlage.
|
||||
*
|
||||
* Er wird beim Einreichen erfasst und steht danach in einer eigenen Spalte -- eine Angabe, keine
|
||||
* Ableitung. Nur Bestandsbelege, die vor der Spalte entstanden sind, leiten ihn noch her.
|
||||
*/
|
||||
class InvoicePurposeTest extends TestCase
|
||||
{
|
||||
@@ -49,7 +59,10 @@ class InvoicePurposeTest extends TestCase
|
||||
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]);
|
||||
|
||||
foreach ([InvoiceStatus::INVOICE_STATUS_NEW, InvoiceStatus::INVOICE_STATUS_APPROVED] as $status) {
|
||||
DB::table('invoice_status')->insert(['slug' => $status]);
|
||||
}
|
||||
|
||||
// Die Beitragserstattung bringt die Migration mit; die beiden anderen Typen nicht.
|
||||
foreach ([
|
||||
@@ -64,6 +77,12 @@ class InvoicePurposeTest extends TestCase
|
||||
'counts_as_expense' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ([UserRole::USER_ROLE_ADMIN, UserRole::USER_ROLE_GROUP_LEADER, UserRole::USER_ROLE_USER] as $role) {
|
||||
UserRole::create(['slug' => $role, 'name' => $role]);
|
||||
}
|
||||
|
||||
Mail::fake();
|
||||
}
|
||||
|
||||
private function makeCostUnit(): CostUnit
|
||||
@@ -79,11 +98,29 @@ class InvoicePurposeTest extends TestCase
|
||||
]);
|
||||
}
|
||||
|
||||
private function purposeOf(array $attributes): string
|
||||
private function makeUser(): User
|
||||
{
|
||||
return User::create([
|
||||
'username' => 'kassenwart-' . uniqid() . '@example.com',
|
||||
'email' => 'kassenwart-' . uniqid() . '@example.com',
|
||||
'firstname' => 'Kim',
|
||||
'lastname' => 'Kasse',
|
||||
'password' => bcrypt('secret'),
|
||||
'local_group' => $this->tenant->slug,
|
||||
'user_role_main' => UserRole::USER_ROLE_USER,
|
||||
'user_role_local_group' => UserRole::USER_ROLE_USER,
|
||||
'active' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ein Beleg direkt in der Datenbank -- so sehen Bestandsbelege aus, deren `purpose` leer ist.
|
||||
*/
|
||||
private function makeInvoice(array $attributes): Invoice
|
||||
{
|
||||
$this->sequence++;
|
||||
|
||||
$invoice = Invoice::create(array_merge([
|
||||
return Invoice::create(array_merge([
|
||||
'tenant' => $this->tenant->slug,
|
||||
'cost_unit_id' => $this->makeCostUnit()->id,
|
||||
'invoice_number' => sprintf('2026-%04d', $this->sequence),
|
||||
@@ -91,10 +128,104 @@ class InvoicePurposeTest extends TestCase
|
||||
'contact_name' => 'Max Mustermann',
|
||||
'amount' => 42.0,
|
||||
], $attributes));
|
||||
|
||||
return new InvoiceResource($invoice)->toArray()['purpose'];
|
||||
}
|
||||
|
||||
private function purposeOf(array $attributes): string
|
||||
{
|
||||
return new InvoiceResource($this->makeInvoice($attributes))->toArray()['purpose'];
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Erfasst beim Einreichen
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Der Weg, den jede eingereichte Abrechnung nimmt. `contactEmail` bleibt leer, damit kein
|
||||
* Bestätigungsmailversand mitläuft.
|
||||
*/
|
||||
private function submit(string $type, ?string $purchase = null, ?string $travelReason = null, ?string $travellers = null): Invoice
|
||||
{
|
||||
return new CreateInvoiceCommand(new CreateInvoiceRequest(
|
||||
costUnit: $this->makeCostUnit(),
|
||||
contactName: 'Max Mustermann',
|
||||
invoiceType: $type,
|
||||
totalAmount: 42.0,
|
||||
receiptFile: null,
|
||||
isDonation: false,
|
||||
invoiceTypeExtended: $purchase,
|
||||
travelReason: $travelReason,
|
||||
travellers: $travellers,
|
||||
))->execute()->invoice;
|
||||
}
|
||||
|
||||
public function test_an_expense_records_what_was_bought(): void
|
||||
{
|
||||
$this->assertSame(
|
||||
'Bastelmaterial Sippenstunde',
|
||||
$this->submit(InvoiceType::INVOICE_TYPE_OTHER, purchase: 'Bastelmaterial Sippenstunde')->purpose
|
||||
);
|
||||
}
|
||||
|
||||
public function test_travel_costs_record_the_reason_and_who_travelled(): void
|
||||
{
|
||||
// Wer gefahren ist, wird gefragt und nicht aus dem Kontaktnamen geraten: Es kann jemand anderes
|
||||
// sein als der, auf dessen Konto das Geld geht.
|
||||
$invoice = $this->submit(
|
||||
InvoiceType::INVOICE_TYPE_TRAVELLING,
|
||||
travelReason: 'Landeslager',
|
||||
travellers: 'Mika und Kim'
|
||||
);
|
||||
|
||||
$this->assertSame('Landeslager — Mika und Kim', $invoice->purpose);
|
||||
}
|
||||
|
||||
public function test_travel_costs_without_travellers_record_only_the_reason(): void
|
||||
{
|
||||
// Ohne Login steht im Formular niemand drin -- das darf den Beleg nicht aufhalten.
|
||||
$invoice = $this->submit(InvoiceType::INVOICE_TYPE_TRAVELLING, travelReason: 'Landeslager');
|
||||
|
||||
$this->assertSame('Landeslager', $invoice->purpose);
|
||||
}
|
||||
|
||||
public function test_a_refund_records_no_purpose(): void
|
||||
{
|
||||
// Beitragserstattungen entstehen ohne Freitext. `null` statt Leerstring: So greift für sie
|
||||
// dieselbe Regel wie für Bestandsbelege.
|
||||
$this->assertNull($this->submit(InvoiceType::INVOICE_TYPE_PARTICIPATION_REFUND)->purpose);
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Die erfasste Spalte gewinnt
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public function test_a_recorded_purpose_beats_the_purchase_note(): void
|
||||
{
|
||||
$this->assertSame('Zeltplatzmiete', $this->purposeOf([
|
||||
'type' => InvoiceType::INVOICE_TYPE_OTHER,
|
||||
'type_other' => 'Bastelmaterial',
|
||||
'purpose' => 'Zeltplatzmiete',
|
||||
]));
|
||||
}
|
||||
|
||||
public function test_a_recorded_purpose_beats_the_travel_derivation(): void
|
||||
{
|
||||
$this->assertSame('Bundeslager — Mika und Kim', $this->purposeOf([
|
||||
'type' => InvoiceType::INVOICE_TYPE_TRAVELLING,
|
||||
'travel_reason' => 'Landeslager',
|
||||
'purpose' => 'Bundeslager — Mika und Kim',
|
||||
]));
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bestandsbelege leiten weiter ab
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public function test_an_expense_shows_what_was_bought(): void
|
||||
{
|
||||
$this->assertSame('Bastelmaterial Sippenstunde', $this->purposeOf([
|
||||
@@ -105,7 +236,8 @@ class InvoicePurposeTest extends TestCase
|
||||
|
||||
public function test_travel_costs_show_the_reason_and_who_travelled(): void
|
||||
{
|
||||
// `type_other` bleibt bei Fahrtkosten leer -- die Strecke landet in `travel_direction`.
|
||||
// `type_other` bleibt bei Fahrtkosten leer -- die Strecke landet in `travel_direction`. Wer
|
||||
// gefahren ist, wurde damals nicht gefragt; dafür steht der Kontaktname.
|
||||
$this->assertSame('Landeslager — Max Mustermann', $this->purposeOf([
|
||||
'type' => InvoiceType::INVOICE_TYPE_TRAVELLING,
|
||||
'travel_direction' => 'Halle – Leipzig',
|
||||
@@ -130,4 +262,68 @@ class InvoicePurposeTest extends TestCase
|
||||
'type' => InvoiceType::INVOICE_TYPE_PARTICIPATION_REFUND,
|
||||
]));
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Korrigierbar, und danach unangetastet
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Der Korrektur-Weg der Kassenwart*in. `UpdateInvoiceCommand` gibt die Abrechnung am Ende frei --
|
||||
* dafür braucht es einen eingeloggten Menschen.
|
||||
*/
|
||||
private function correct(Invoice $invoice, ?string $purpose): Invoice
|
||||
{
|
||||
$this->actingAs($this->makeUser());
|
||||
|
||||
new UpdateInvoiceCommand(new UpdateInvoiceRequest(
|
||||
$invoice,
|
||||
$invoice->comment,
|
||||
$invoice->invoiceType(),
|
||||
$invoice->costUnit()->first(),
|
||||
Amount::fromString($invoice->amount),
|
||||
$purpose
|
||||
))->execute();
|
||||
|
||||
return $invoice->fresh();
|
||||
}
|
||||
|
||||
public function test_a_corrected_purpose_is_stored_and_logged(): void
|
||||
{
|
||||
$invoice = $this->correct(
|
||||
$this->makeInvoice(['type' => InvoiceType::INVOICE_TYPE_OTHER, 'type_other' => 'Bastelmaterial']),
|
||||
'Material für den Bastelnachmittag'
|
||||
);
|
||||
|
||||
$this->assertSame('Material für den Bastelnachmittag', $invoice->purpose);
|
||||
$this->assertSame('Material für den Bastelnachmittag', $invoice->purposeText());
|
||||
$this->assertStringContainsString('Zahlungsgrund geändert', $invoice->changes);
|
||||
}
|
||||
|
||||
public function test_an_untouched_purpose_is_not_frozen(): void
|
||||
{
|
||||
// Das Formular ist mit dem angezeigten Text vorbelegt. Wer ihn unverändert abschickt, hat nichts
|
||||
// geändert -- ein Bestandsbeleg behält seine leere Spalte und leitet weiter ab.
|
||||
$invoice = $this->correct(
|
||||
$this->makeInvoice(['type' => InvoiceType::INVOICE_TYPE_OTHER, 'type_other' => 'Bastelmaterial']),
|
||||
'Bastelmaterial'
|
||||
);
|
||||
|
||||
$this->assertNull($invoice->purpose);
|
||||
$this->assertSame('Bastelmaterial', $invoice->purposeText());
|
||||
$this->assertStringNotContainsString('Zahlungsgrund', (string) $invoice->changes);
|
||||
}
|
||||
|
||||
public function test_the_comment_of_a_correction_stays_out_of_the_purpose(): void
|
||||
{
|
||||
// Die Anmerkung der Korrektur gehört auf den Beleg, nicht in den Zahlungsgrund.
|
||||
$invoice = $this->makeInvoice([
|
||||
'type' => InvoiceType::INVOICE_TYPE_OTHER,
|
||||
'type_other' => 'Bastelmaterial',
|
||||
'comment' => 'Betrag nach Rücksprache korrigiert',
|
||||
]);
|
||||
|
||||
$this->assertSame('Bastelmaterial', $this->correct($invoice, 'Bastelmaterial')->purposeText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
<?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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user