Files
mareike/tests/Feature/InvoicePurposeTest.php
T

134 lines
4.5 KiB
PHP
Raw 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\Enumerations\CostUnitType;
use App\Enumerations\InvoiceStatus;
use App\Enumerations\InvoiceType;
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 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.
*/
class InvoicePurposeTest extends TestCase
{
use RefreshDatabase;
private Tenant $tenant;
private int $sequence = 0;
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]);
// Die Beitragserstattung bringt die Migration mit; die beiden anderen Typen nicht.
foreach ([
InvoiceType::INVOICE_TYPE_TRAVELLING => 'Fahrtkosten',
InvoiceType::INVOICE_TYPE_OTHER => 'Sonstige Kosten',
] as $slug => $name) {
DB::table('invoice_types')->insert([
'slug' => $slug,
'name' => $name,
'sort_order' => 1,
'selectable' => true,
'counts_as_expense' => true,
]);
}
}
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,
]);
}
private function purposeOf(array $attributes): string
{
$this->sequence++;
$invoice = Invoice::create(array_merge([
'tenant' => $this->tenant->slug,
'cost_unit_id' => $this->makeCostUnit()->id,
'invoice_number' => sprintf('2026-%04d', $this->sequence),
'status' => InvoiceStatus::INVOICE_STATUS_NEW,
'contact_name' => 'Max Mustermann',
'amount' => 42.0,
], $attributes));
return new InvoiceResource($invoice)->toArray()['purpose'];
}
public function test_an_expense_shows_what_was_bought(): void
{
$this->assertSame('Bastelmaterial Sippenstunde', $this->purposeOf([
'type' => InvoiceType::INVOICE_TYPE_OTHER,
'type_other' => 'Bastelmaterial Sippenstunde',
]));
}
public function test_travel_costs_show_the_reason_and_who_travelled(): void
{
// `type_other` bleibt bei Fahrtkosten leer -- die Strecke landet in `travel_direction`.
$this->assertSame('Landeslager — Max Mustermann', $this->purposeOf([
'type' => InvoiceType::INVOICE_TYPE_TRAVELLING,
'travel_direction' => 'Halle Leipzig',
'travel_reason' => 'Landeslager',
]));
}
public function test_travel_costs_without_a_reason_still_name_the_person(): void
{
// Altbestand: der Reisegrund wurde erst später zur Pflicht. Kein führendes " — ".
$this->assertSame('Max Mustermann', $this->purposeOf([
'type' => InvoiceType::INVOICE_TYPE_TRAVELLING,
'travel_direction' => 'Halle Leipzig',
]));
}
public function test_an_invoice_without_a_purpose_stays_empty(): void
{
// Beitragserstattungen entstehen ohne Freitext, ältere Belege haben keinen. Ein "--" würde in
// der Liste nur Platz kosten.
$this->assertSame('', $this->purposeOf([
'type' => InvoiceType::INVOICE_TYPE_PARTICIPATION_REFUND,
]));
}
}