Zahlungszwecke
This commit is contained in:
@@ -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