332 lines
15 KiB
PHP
332 lines
15 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Domains\Event\Actions\ShortSignUp\ShortSignUpCommand;
|
|
use App\Domains\Event\Actions\ShortSignUp\ShortSignUpRequest;
|
|
use App\Enumerations\EatingHabit;
|
|
use App\Enumerations\EfzStatus;
|
|
use App\Enumerations\FirstAidPermission;
|
|
use App\Enumerations\ParticipationType;
|
|
use App\Enumerations\SwimmingPermission;
|
|
use App\Models\Event;
|
|
use App\Models\EventParticipant;
|
|
use App\Models\PaymentMethod;
|
|
use App\Models\Tenant;
|
|
use App\RelationModels\EventParticipationFee;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use Tests\TestCase;
|
|
|
|
class ShortSignUpTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
private Tenant $tenant;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
Mail::fake();
|
|
|
|
$this->tenant = Tenant::create([
|
|
'slug' => 'tv', 'name' => 'Test', 'email' => 't@example.com', 'email_finance' => 'f@example.com',
|
|
'url' => 'test.local', 'account_name' => 'Test e.V.', 'account_iban' => 'DE00', 'account_bic' => 'XY',
|
|
'city' => 'Stadt', 'postcode' => '00000', 'is_active_local_group' => true, 'has_active_instance' => true,
|
|
]);
|
|
app()->instance('tenant', $this->tenant);
|
|
|
|
PaymentMethod::create(['slug' => PaymentMethod::PAYMENT_ACCOUNT_TRANSACTION]);
|
|
DB::table('participation_fee_types')->insert(['slug' => 'FIXED', 'name' => 'Fixed', 'created_at' => now(), 'updated_at' => now()]);
|
|
ParticipationType::create(['slug' => ParticipationType::PARTICIPATION_TYPE_PARTICIPANT, 'name' => 'Teilnehmende']);
|
|
EfzStatus::create(['slug' => EfzStatus::EFZ_STATUS_NOT_CHECKED, 'name' => 'Nicht geprüft']);
|
|
EfzStatus::create(['slug' => EfzStatus::EFZ_STATUS_NOT_REQUIRED, 'name' => 'Nicht erforderlich']);
|
|
SwimmingPermission::create(['slug' => SwimmingPermission::SWIMMING_PERMISSION_ALLOWED, 'name' => 'Darf baden', 'short' => 'Erteilt']);
|
|
SwimmingPermission::create(['slug' => SwimmingPermission::SWIMMING_PERMISSION_DENIED, 'name' => 'Darf nicht baden', 'short' => 'Keine']);
|
|
FirstAidPermission::create(['slug' => FirstAidPermission::FIRST_AID_PERMISSION_ALLOWED, 'name' => 'Zugestimmt', 'description' => '']);
|
|
FirstAidPermission::create(['slug' => FirstAidPermission::FIRST_AID_PERMISSION_DENIED, 'name' => 'Abgelehnt', 'description' => '']);
|
|
EatingHabit::create(['slug' => EatingHabit::EATING_HABIT_OMNIVOR, 'name' => 'Omnivor']);
|
|
}
|
|
|
|
private function createEvent(bool $withFee = true, bool $swimmingPermissionRequired = true): Event
|
|
{
|
|
$event = Event::create([
|
|
'tenant' => $this->tenant->slug, 'name' => 'Event', 'identifier' => 'evt-1', 'location' => 'Ort',
|
|
'postal_code' => '00000', 'email' => 'e@example.com', 'start_date' => '2026-08-01', 'end_date' => '2026-08-05',
|
|
'early_bird_end' => '2026-07-01', 'registration_final_end' => '2026-07-20', 'early_bird_end_amount_increase' => 0,
|
|
'account_owner' => 'Owner', 'account_iban' => 'DE00', 'participation_fee_type' => 'FIXED',
|
|
'pay_per_day' => false, 'pay_direct' => false,
|
|
'short_registration' => true, 'swimming_permission_required' => $swimmingPermissionRequired,
|
|
]);
|
|
|
|
if ($withFee) {
|
|
$fee = EventParticipationFee::create([
|
|
'tenant' => $this->tenant->slug, 'type' => ParticipationType::PARTICIPATION_TYPE_PARTICIPANT,
|
|
'name' => 'Teilnahme', 'description' => '', 'amount_standard' => 50.0,
|
|
'amount_reduced' => 30.0, 'amount_solidarity' => 70.0,
|
|
]);
|
|
$event->participation_fee_1 = $fee->id;
|
|
$event->save();
|
|
$event->refresh();
|
|
}
|
|
|
|
return $event;
|
|
}
|
|
|
|
private function shortRequest(Event $event, array $overrides = []): ShortSignUpRequest
|
|
{
|
|
return new ShortSignUpRequest(
|
|
event: $event,
|
|
user_id: null,
|
|
firstname: $overrides['firstname'] ?? 'Hans',
|
|
lastname: $overrides['lastname'] ?? 'Muster',
|
|
nickname: $overrides['nickname'] ?? null,
|
|
// Volljährig, sofern nicht anders angegeben.
|
|
birthday: $overrides['birthday'] ?? new \DateTime('2000-01-01'),
|
|
email: $overrides['email'] ?? 'h@example.com',
|
|
phone: $overrides['phone'] ?? '123',
|
|
localGroupId: $overrides['localGroupId'] ?? null,
|
|
contactPerson: $overrides['contactPerson'] ?? null,
|
|
contactEmail: $overrides['contactEmail'] ?? null,
|
|
allergies: $overrides['allergies'] ?? null,
|
|
intolerances: $overrides['intolerances'] ?? null,
|
|
firstAidPermission: $overrides['firstAidPermission'] ?? null,
|
|
swimmingPermission: $overrides['swimmingPermission'] ?? null,
|
|
foto_socialmedia: true,
|
|
foto_print: false,
|
|
foto_webseite: false,
|
|
foto_partner: false,
|
|
foto_intern: false,
|
|
paymentMethod: $overrides['paymentMethod'] ?? PaymentMethod::PAYMENT_ACCOUNT_TRANSACTION,
|
|
paymentOptions: [],
|
|
participationOptions: $overrides['participationOptions'] ?? [],
|
|
);
|
|
}
|
|
|
|
public function test_kurzanmeldung_fuellt_nicht_erhobene_pflichtfelder(): void
|
|
{
|
|
$event = $this->createEvent();
|
|
|
|
$response = new ShortSignUpCommand($this->shortRequest($event))->execute();
|
|
|
|
$this->assertTrue($response->success, $response->message ?? '');
|
|
$participant = $response->participant;
|
|
|
|
$this->assertSame('Nicht erforderlich', $participant->address_1);
|
|
$this->assertSame('Nicht erforderlich', $participant->city);
|
|
$this->assertSame('00000', $participant->postcode);
|
|
$this->assertNull($participant->local_group);
|
|
$this->assertNull($participant->address_2);
|
|
$this->assertNull($participant->medications);
|
|
|
|
// Zeitraum und Mahlzeiten kommen aus der Veranstaltung.
|
|
$this->assertSame('2026-08-01', $participant->arrival_date->format('Y-m-d'));
|
|
$this->assertSame('2026-08-05', $participant->departure_date->format('Y-m-d'));
|
|
$this->assertSame(1, $participant->arrival_eating);
|
|
$this->assertSame(2, $participant->departure_eating);
|
|
|
|
// Gruppe und Beitragsstufe stehen fest.
|
|
$this->assertSame(ParticipationType::PARTICIPATION_TYPE_PARTICIPANT, $participant->participation_type);
|
|
$this->assertSame('standard', $participant->fee_type);
|
|
$this->assertSame(50.0, $participant->amount->getAmount());
|
|
$this->assertSame(EatingHabit::EATING_HABIT_OMNIVOR, $participant->eating_habit);
|
|
|
|
// Volljährige brauchen keine Erlaubnisse.
|
|
$this->assertSame(SwimmingPermission::SWIMMING_PERMISSION_ALLOWED, $participant->swimming_permission);
|
|
$this->assertSame(FirstAidPermission::FIRST_AID_PERMISSION_ALLOWED, $participant->first_aid_permission);
|
|
|
|
$this->assertSame(1, $participant->invoice_sequence);
|
|
$this->assertTrue($participant->foto_socialmedia);
|
|
$this->assertFalse($participant->foto_print);
|
|
}
|
|
|
|
public function test_u18_ohne_abgefragte_badeerlaubnis_bekommt_keine(): void
|
|
{
|
|
$event = $this->createEvent(swimmingPermissionRequired: false);
|
|
|
|
$response = new ShortSignUpCommand($this->shortRequest($event, [
|
|
'birthday' => new \DateTime('2015-01-01'),
|
|
'contactPerson' => 'Muster, Maria',
|
|
'contactEmail' => 'maria@example.com',
|
|
'firstAidPermission' => FirstAidPermission::FIRST_AID_PERMISSION_ALLOWED,
|
|
]))->execute();
|
|
|
|
$this->assertTrue($response->success, $response->message ?? '');
|
|
$this->assertSame(SwimmingPermission::SWIMMING_PERMISSION_DENIED, $response->participant->swimming_permission);
|
|
$this->assertSame(EfzStatus::EFZ_STATUS_NOT_REQUIRED, $response->participant->efz_status);
|
|
$this->assertSame('Muster, Maria', $response->participant->contact_person);
|
|
$this->assertSame('maria@example.com', $response->participant->email_2);
|
|
}
|
|
|
|
public function test_u18_uebernimmt_gewaehlte_badeerlaubnis(): void
|
|
{
|
|
$event = $this->createEvent();
|
|
|
|
$response = new ShortSignUpCommand($this->shortRequest($event, [
|
|
'birthday' => new \DateTime('2015-01-01'),
|
|
'contactPerson' => 'Muster, Maria',
|
|
'contactEmail' => 'maria@example.com',
|
|
'firstAidPermission' => FirstAidPermission::FIRST_AID_PERMISSION_DENIED,
|
|
'swimmingPermission' => SwimmingPermission::SWIMMING_PERMISSION_ALLOWED,
|
|
]))->execute();
|
|
|
|
$this->assertTrue($response->success, $response->message ?? '');
|
|
$this->assertSame(SwimmingPermission::SWIMMING_PERMISSION_ALLOWED, $response->participant->swimming_permission);
|
|
$this->assertSame(FirstAidPermission::FIRST_AID_PERMISSION_DENIED, $response->participant->first_aid_permission);
|
|
}
|
|
|
|
public function test_u18_ohne_kontaktperson_wird_abgelehnt(): void
|
|
{
|
|
$event = $this->createEvent();
|
|
|
|
$response = new ShortSignUpCommand($this->shortRequest($event, [
|
|
'birthday' => new \DateTime('2015-01-01'),
|
|
]))->execute();
|
|
|
|
$this->assertFalse($response->success);
|
|
$this->assertSame(0, EventParticipant::count());
|
|
}
|
|
|
|
public function test_ohne_teilnahmegruppe_wird_abgelehnt(): void
|
|
{
|
|
$event = $this->createEvent(withFee: false);
|
|
|
|
$response = new ShortSignUpCommand($this->shortRequest($event))->execute();
|
|
|
|
$this->assertFalse($response->success);
|
|
$this->assertNotNull($response->message);
|
|
$this->assertSame(0, EventParticipant::count());
|
|
}
|
|
|
|
public function test_teilnahmeoptionen_werden_gespeichert(): void
|
|
{
|
|
$event = $this->createEvent();
|
|
$event->participation_options = [[
|
|
'key' => 'shirt',
|
|
'title' => 'T-Shirt',
|
|
'label' => 'T-Shirt-Größe',
|
|
'options' => [['value' => 'm', 'label' => 'M'], ['value' => 'l', 'label' => 'L']],
|
|
]];
|
|
$event->save();
|
|
|
|
$response = new ShortSignUpCommand($this->shortRequest($event, [
|
|
'participationOptions' => ['shirt' => 'l'],
|
|
]))->execute();
|
|
|
|
$this->assertTrue($response->success, $response->message ?? '');
|
|
$options = $response->participant->selectedOptions()->get();
|
|
$this->assertCount(1, $options);
|
|
$this->assertSame('shirt', $options->first()->question_key);
|
|
$this->assertSame('L', $options->first()->value_label);
|
|
}
|
|
|
|
public function test_unbeantwortete_teilnahmeoption_wird_abgelehnt(): void
|
|
{
|
|
$event = $this->createEvent();
|
|
$event->participation_options = [[
|
|
'key' => 'shirt',
|
|
'title' => 'T-Shirt',
|
|
'label' => 'T-Shirt-Größe',
|
|
'options' => [['value' => 'm', 'label' => 'M']],
|
|
]];
|
|
$event->save();
|
|
|
|
$response = new ShortSignUpCommand($this->shortRequest($event))->execute();
|
|
|
|
$this->assertFalse($response->success);
|
|
$this->assertSame(0, EventParticipant::count());
|
|
}
|
|
|
|
private function createLocalGroup(string $slug, string $name): Tenant
|
|
{
|
|
return Tenant::create([
|
|
'slug' => $slug, 'name' => $name, 'email' => $slug . '@example.com',
|
|
'email_finance' => $slug . '-f@example.com', 'url' => $slug . '.local',
|
|
'account_name' => $name, 'account_iban' => 'DE00', 'account_bic' => 'XY',
|
|
'city' => 'Stadt', 'postcode' => '00000', 'is_active_local_group' => true,
|
|
'has_active_instance' => false,
|
|
]);
|
|
}
|
|
|
|
public function test_einziger_stamm_wird_ohne_auswahl_zugeordnet(): void
|
|
{
|
|
$event = $this->createEvent();
|
|
$group = $this->createLocalGroup('stamm-a', 'Stamm A');
|
|
$event->localGroups()->attach($group->id);
|
|
$event->refresh();
|
|
|
|
$response = new ShortSignUpCommand($this->shortRequest($event))->execute();
|
|
|
|
$this->assertTrue($response->success, $response->message ?? '');
|
|
$this->assertSame('stamm-a', $response->participant->local_group);
|
|
}
|
|
|
|
public function test_bei_mehreren_staemmen_wird_die_auswahl_uebernommen(): void
|
|
{
|
|
$event = $this->createEvent();
|
|
$first = $this->createLocalGroup('stamm-a', 'Stamm A');
|
|
$second = $this->createLocalGroup('stamm-b', 'Stamm B');
|
|
$event->localGroups()->attach([$first->id, $second->id]);
|
|
$event->refresh();
|
|
|
|
$response = new ShortSignUpCommand($this->shortRequest($event, [
|
|
'localGroupId' => $second->id,
|
|
]))->execute();
|
|
|
|
$this->assertTrue($response->success, $response->message ?? '');
|
|
$this->assertSame('stamm-b', $response->participant->local_group);
|
|
}
|
|
|
|
public function test_bei_mehreren_staemmen_ist_die_auswahl_pflicht(): void
|
|
{
|
|
$event = $this->createEvent();
|
|
$first = $this->createLocalGroup('stamm-a', 'Stamm A');
|
|
$second = $this->createLocalGroup('stamm-b', 'Stamm B');
|
|
$event->localGroups()->attach([$first->id, $second->id]);
|
|
$event->refresh();
|
|
|
|
$response = new ShortSignUpCommand($this->shortRequest($event))->execute();
|
|
|
|
$this->assertFalse($response->success);
|
|
$this->assertSame(0, EventParticipant::count());
|
|
}
|
|
|
|
public function test_nicht_teilnehmender_stamm_wird_abgelehnt(): void
|
|
{
|
|
$event = $this->createEvent();
|
|
$first = $this->createLocalGroup('stamm-a', 'Stamm A');
|
|
$second = $this->createLocalGroup('stamm-b', 'Stamm B');
|
|
$event->localGroups()->attach([$first->id, $second->id]);
|
|
$event->refresh();
|
|
|
|
// Stamm existiert, nimmt aber nicht an der Veranstaltung teil.
|
|
$foreign = $this->createLocalGroup('stamm-c', 'Stamm C');
|
|
|
|
$response = new ShortSignUpCommand($this->shortRequest($event, [
|
|
'localGroupId' => $foreign->id,
|
|
]))->execute();
|
|
|
|
$this->assertFalse($response->success);
|
|
$this->assertSame(0, EventParticipant::count());
|
|
}
|
|
|
|
public function test_resource_ueberlebt_kurzanmeldung(): void
|
|
{
|
|
$event = $this->createEvent();
|
|
|
|
$response = new ShortSignUpCommand($this->shortRequest($event))->execute();
|
|
$this->assertTrue($response->success, $response->message ?? '');
|
|
|
|
// Regressionswächter für Teilnehmerliste, Detailansicht und CSV-Export.
|
|
$array = $response->participant->toResource()->toArray(request());
|
|
|
|
$this->assertSame('Nicht im LV', $array['localgroup']);
|
|
$this->assertSame('Erteilt', $array['swimmingPermission']);
|
|
$this->assertSame('Zugestimmt', $array['extendedFirstAid']);
|
|
$this->assertSame('Omnivor', $array['eatingHabit']);
|
|
$this->assertSame('Teilnehmende', $array['participationType']);
|
|
}
|
|
}
|