Anschrift für Veranstaltungsort

This commit is contained in:
2026-09-10 11:45:52 +02:00
parent 70a57d10f5
commit ddfaab1501
19 changed files with 306 additions and 10 deletions
@@ -33,7 +33,7 @@ function navigateTo(url) {
</tr> </tr>
<tr> <tr>
<td> <td>
{{participation.event.postal_code}} {{participation.event.location}}<br /> {{participation.eventAddress}}<br />
</td> </td>
<td> <td>
<a class="link" :href="`/api/v1/event/participant/${participation.identifier}/ical`">In Kalender importieren</a> <a class="link" :href="`/api/v1/event/participant/${participation.identifier}/ical`">In Kalender importieren</a>
@@ -38,6 +38,8 @@ class CreateEventCommand {
'name' => $this->request->name, 'name' => $this->request->name,
'identifier' => Str::random(10), 'identifier' => Str::random(10),
'location' => $this->request->location, 'location' => $this->request->location,
'street' => $this->normalizeOptional($this->request->street),
'house_number' => $this->normalizeOptional($this->request->houseNumber),
'postal_code' => $this->request->postalCode, 'postal_code' => $this->request->postalCode,
'email' => $this->request->email, 'email' => $this->request->email,
'start_date' => $this->request->begin, 'start_date' => $this->request->begin,
@@ -107,6 +109,17 @@ class CreateEventCommand {
return $response; return $response;
} }
/**
* Straße und Hausnummer sind optional. Ein leer gelassenes Eingabefeld liefert einen leeren String --
* gespeichert wird dafür `null`, damit „nicht angegeben" nur eine Darstellung hat.
*/
private function normalizeOptional(?string $value): ?string
{
$value = trim((string) $value);
return '' === $value ? null : $value;
}
/** /**
* Event-Teil der Rechnungsnummer, z.B. `WM-V-20260701`: Tenant-Präfix, Dokumentart „V" für * Event-Teil der Rechnungsnummer, z.B. `WM-V-20260701`: Tenant-Präfix, Dokumentart „V" für
* Veranstaltung, dann ohne Trenner Jahr, Monat des Beginns und die laufende Nummer der * Veranstaltung, dann ohne Trenner Jahr, Monat des Beginns und die laufende Nummer der
@@ -19,8 +19,10 @@ class CreateEventRequest {
public string $accountOwner; public string $accountOwner;
public string $accountIban; public string $accountIban;
public bool $payPerDay; public bool $payPerDay;
public ?string $street;
public ?string $houseNumber;
public function __construct(string $name, string $location, string $postalCode, string $email, DateTime $begin, DateTime $end, DateTime $earlyBirdEnd, DateTime $registrationFinalEnd, int $earlyBirdEndAmountIncrease, ParticipationFeeType $participationFeeType, string $accountOwner, string $accountIban, bool $payPerDay) { public function __construct(string $name, string $location, string $postalCode, string $email, DateTime $begin, DateTime $end, DateTime $earlyBirdEnd, DateTime $registrationFinalEnd, int $earlyBirdEndAmountIncrease, ParticipationFeeType $participationFeeType, string $accountOwner, string $accountIban, bool $payPerDay, ?string $street = null, ?string $houseNumber = null) {
$this->name = $name; $this->name = $name;
$this->location = $location; $this->location = $location;
$this->postalCode = $postalCode; $this->postalCode = $postalCode;
@@ -34,5 +36,7 @@ class CreateEventRequest {
$this->accountOwner = $accountOwner; $this->accountOwner = $accountOwner;
$this->accountIban = $accountIban; $this->accountIban = $accountIban;
$this->payPerDay = $payPerDay; $this->payPerDay = $payPerDay;
$this->street = $street;
$this->houseNumber = $houseNumber;
} }
} }
@@ -18,7 +18,7 @@ class GenerateIcalCommand
$dtEnd = $event->end_date->copy()->addDay()->format('Ymd'); $dtEnd = $event->end_date->copy()->addDay()->format('Ymd');
$now = now()->format('Ymd\THis\Z'); $now = now()->format('Ymd\THis\Z');
$summary = $this->escapeIcal($event->name); $summary = $this->escapeIcal($event->name);
$location = $this->escapeIcal(trim($event->postal_code . ' ' . $event->location)); $location = $this->escapeIcal($event->getFullAddress());
$description = $this->escapeIcal('Teilnahme als: ' . $participant->getOfficialName()); $description = $this->escapeIcal('Teilnahme als: ' . $participant->getOfficialName());
$icalContent = implode("\r\n", [ $icalContent = implode("\r\n", [
@@ -13,6 +13,8 @@ class UpdateEventCommand {
$this->request->event->name = $this->request->eventName; $this->request->event->name = $this->request->eventName;
$this->request->event->location = $this->request->eventLocation; $this->request->event->location = $this->request->eventLocation;
$this->request->event->street = $this->normalizeOptional($this->request->street);
$this->request->event->house_number = $this->normalizeOptional($this->request->houseNumber);
$this->request->event->postal_code = $this->request->postalCode; $this->request->event->postal_code = $this->request->postalCode;
$this->request->event->email = $this->request->email; $this->request->event->email = $this->request->email;
$this->request->event->early_bird_end = $this->request->earlyBirdEnd; $this->request->event->early_bird_end = $this->request->earlyBirdEnd;
@@ -42,4 +44,15 @@ class UpdateEventCommand {
return $response; return $response;
} }
/**
* Straße und Hausnummer sind optional. Ein geleertes Eingabefeld liefert einen leeren String --
* gespeichert wird dafür `null`, damit „nicht angegeben" nur eine Darstellung hat.
*/
private function normalizeOptional(?string $value): ?string
{
$value = trim((string) $value);
return '' === $value ? null : $value;
}
} }
@@ -10,6 +10,8 @@ class UpdateEventRequest {
public Event $event; public Event $event;
public string $eventName; public string $eventName;
public string $eventLocation; public string $eventLocation;
public ?string $street;
public ?string $houseNumber;
public string $postalCode; public string $postalCode;
public string $email; public string $email;
public DateTime $earlyBirdEnd; public DateTime $earlyBirdEnd;
@@ -24,11 +26,13 @@ class UpdateEventRequest {
public array $contributingLocalGroups; public array $contributingLocalGroups;
public array $eatingHabits; public array $eatingHabits;
public function __construct(Event $event, string $eventName, string $eventLocation, string $postalCode, string $email, DateTime $earlyBirdEnd, DateTime $registrationFinalEnd, int $alcoholicsAge, bool $sendWeeklyReports, bool $registrationAllowed, Amount $flatSupport, Amount $supportPerPerson, array $contributingLocalGroups, array $eatingHabits, bool $shortRegistration = false, bool $swimmingPermissionRequired = true) public function __construct(Event $event, string $eventName, string $eventLocation, string $postalCode, string $email, DateTime $earlyBirdEnd, DateTime $registrationFinalEnd, int $alcoholicsAge, bool $sendWeeklyReports, bool $registrationAllowed, Amount $flatSupport, Amount $supportPerPerson, array $contributingLocalGroups, array $eatingHabits, bool $shortRegistration = false, bool $swimmingPermissionRequired = true, ?string $street = null, ?string $houseNumber = null)
{ {
$this->event = $event; $this->event = $event;
$this->eventName = $eventName; $this->eventName = $eventName;
$this->eventLocation = $eventLocation; $this->eventLocation = $eventLocation;
$this->street = $street;
$this->houseNumber = $houseNumber;
$this->postalCode = $postalCode; $this->postalCode = $postalCode;
$this->email = $email; $this->email = $email;
$this->earlyBirdEnd = $earlyBirdEnd; $this->earlyBirdEnd = $earlyBirdEnd;
@@ -17,6 +17,7 @@ class ArchivedEventsController extends CommonController
'name' => $event->name, 'name' => $event->name,
'location' => $event->location, 'location' => $event->location,
'postalCode' => $event->postal_code, 'postalCode' => $event->postal_code,
'fullAddress' => $event->getFullAddress(),
'eventBegin' => $event->start_date->format('d.m.Y'), 'eventBegin' => $event->start_date->format('d.m.Y'),
'eventEnd' => $event->end_date->format('d.m.Y'), 'eventEnd' => $event->end_date->format('d.m.Y'),
]; ];
@@ -56,7 +56,9 @@ class CreateController extends CommonController {
$participationFeeType, $participationFeeType,
$request->input('eventAccount'), $request->input('eventAccount'),
$request->input('eventIban'), $request->input('eventIban'),
$payPerDay $payPerDay,
$request->input('eventStreet'),
$request->input('eventHouseNumber')
); );
$wasSuccessful = false; $wasSuccessful = false;
@@ -63,6 +63,8 @@ class DetailsController extends CommonController {
$eatingHabits, $eatingHabits,
(bool)$request->input('shortRegistration', false), (bool)$request->input('shortRegistration', false),
(bool)$request->input('swimmingPermissionRequired', true), (bool)$request->input('swimmingPermissionRequired', true),
$request->input('street'),
$request->input('houseNumber'),
); );
$eventUpdateCommand = new UpdateEventCommand($eventUpdateRequest); $eventUpdateCommand = new UpdateEventCommand($eventUpdateRequest);
+1 -1
View File
@@ -47,7 +47,7 @@ async function unarchiveEvent(eventId) {
<div> <div>
<h2 style="margin: 0 0 4px 0; font-size: 1.1rem; font-weight: 600;">{{ event.name }}</h2> <h2 style="margin: 0 0 4px 0; font-size: 1.1rem; font-weight: 600;">{{ event.name }}</h2>
<span style="color: #6b7280; font-size: 0.875rem;"> <span style="color: #6b7280; font-size: 0.875rem;">
{{ event.postalCode }} {{ event.location }} {{ event.fullAddress }}
&nbsp;·&nbsp; &nbsp;·&nbsp;
{{ event.eventBegin }} {{ event.eventEnd }} {{ event.eventBegin }} {{ event.eventEnd }}
</span> </span>
+14
View File
@@ -23,6 +23,8 @@
eventName: '', eventName: '',
eventPostalCode: '', eventPostalCode: '',
eventLocation: '', eventLocation: '',
eventStreet: '',
eventHouseNumber: '',
eventEmail: props.emailAddress ? props.emailAddress : '', eventEmail: props.emailAddress ? props.emailAddress : '',
eventBegin: '', eventBegin: '',
eventEnd: '', eventEnd: '',
@@ -145,6 +147,8 @@
eventName: formData.eventName, eventName: formData.eventName,
eventPostalCode: formData.eventPostalCode, eventPostalCode: formData.eventPostalCode,
eventLocation: formData.eventLocation, eventLocation: formData.eventLocation,
eventStreet: formData.eventStreet,
eventHouseNumber: formData.eventHouseNumber,
eventEmail: formData.eventEmail, eventEmail: formData.eventEmail,
eventBegin: formData.eventBegin, eventBegin: formData.eventBegin,
eventEnd: formData.eventEnd, eventEnd: formData.eventEnd,
@@ -195,6 +199,16 @@
<ErrorText :message="errors.eventLocation" /></td> <ErrorText :message="errors.eventLocation" /></td>
</tr> </tr>
<tr style="vertical-align: top;">
<th class="width-medium pr-20 height-50">Straße (optional)</th>
<td class="height-50"><input type="text" v-model="formData.eventStreet" class="width-half-full" /></td>
</tr>
<tr style="vertical-align: top;">
<th class="width-medium pr-20 height-50">Hausnummer (optional)</th>
<td class="height-50"><input type="text" v-model="formData.eventHouseNumber" class="width-half-full" /></td>
</tr>
<tr style="vertical-align: top;"> <tr style="vertical-align: top;">
<th class="width-medium pr-20 height-50">Postleitzahl des Veranstaltungsorts</th> <th class="width-medium pr-20 height-50">Postleitzahl des Veranstaltungsorts</th>
<td class="height-50"><input type="text" v-model="formData.eventPostalCode" class="width-half-full" /> <td class="height-50"><input type="text" v-model="formData.eventPostalCode" class="width-half-full" />
@@ -22,7 +22,7 @@ const props = defineProps({
<div class="available-event-header"> <div class="available-event-header">
<div> <div>
<h2 class="available-event-title">{{ event.name }}</h2> <h2 class="available-event-title">{{ event.name }}</h2>
<span class="available-event-location">{{ event.postalCode }} {{ event.location }}</span> <span class="available-event-location">{{ event.fullAddress }}</span>
</div> </div>
<span <span
v-if="event.registrationAllowed" v-if="event.registrationAllowed"
@@ -47,7 +47,7 @@ const props = defineProps({
</tr> </tr>
<tr> <tr>
<th>Veranstaltungsort</th> <th>Veranstaltungsort</th>
<td>{{ event.postalCode }} {{ event.location }}</td> <td>{{ event.fullAddress }}</td>
</tr> </tr>
<tr> <tr>
<th>Frühbuchen bis</th> <th>Frühbuchen bis</th>
@@ -27,6 +27,8 @@ const emit = defineEmits(['close'])
contributingLocalGroups: contributingLocalGroups.value, contributingLocalGroups: contributingLocalGroups.value,
eventName: props.event.name, eventName: props.event.name,
eventLocation: props.event.location, eventLocation: props.event.location,
street: props.event.street ?? '',
houseNumber: props.event.houseNumber ?? '',
postalCode: props.event.postalCode, postalCode: props.event.postalCode,
email: props.event.email, email: props.event.email,
earlyBirdEnd: props.event.earlyBirdEnd.internal, earlyBirdEnd: props.event.earlyBirdEnd.internal,
@@ -59,6 +61,8 @@ const emit = defineEmits(['close'])
body: { body: {
eventName: formData.eventName, eventName: formData.eventName,
eventLocation: formData.eventLocation, eventLocation: formData.eventLocation,
street: formData.street,
houseNumber: formData.houseNumber,
postalCode: formData.postalCode, postalCode: formData.postalCode,
email: formData.email, email: formData.email,
earlyBirdEnd: formData.earlyBirdEnd, earlyBirdEnd: formData.earlyBirdEnd,
@@ -109,6 +113,20 @@ const emit = defineEmits(['close'])
</td> </td>
</tr> </tr>
<tr>
<th>Straße (optional)</th>
<td>
<input type="text" v-model="formData.street" class="width-full" />
</td>
</tr>
<tr>
<th>Hausnummer (optional)</th>
<td>
<input type="text" v-model="formData.houseNumber" class="width-full" />
</td>
</tr>
<tr> <tr>
<th>Postleitzahl des Veranstaltungsorts</th> <th>Postleitzahl des Veranstaltungsorts</th>
<td> <td>
+2 -2
View File
@@ -38,7 +38,7 @@ function close() {
</span> </span>
</div> </div>
<p class="signup-event-location"> <p class="signup-event-location">
📍 {{ props.event.postalCode }} {{ props.event.location }} 📍 {{ props.event.fullAddress }}
</p> </p>
</div> </div>
<div v-else class="signup-header signup-header--closed"> <div v-else class="signup-header signup-header--closed">
@@ -49,7 +49,7 @@ function close() {
</span> </span>
</div> </div>
<p class="signup-event-location"> <p class="signup-event-location">
📍 {{ props.event.postalCode }} {{ props.event.location }} 📍 {{ props.event.fullAddress }}
</p> </p>
</div> </div>
+16
View File
@@ -19,6 +19,8 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
* @property int $cost_unit_id * @property int $cost_unit_id
* @property string $name * @property string $name
* @property string $location * @property string $location
* @property string|null $street
* @property string|null $house_number
* @property string $postal_code * @property string $postal_code
* @property string $email * @property string $email
* @property DateTime $start_date * @property DateTime $start_date
@@ -59,6 +61,8 @@ class Event extends InstancedModel
'name', 'name',
'identifier', 'identifier',
'location', 'location',
'street',
'house_number',
'postal_code', 'postal_code',
'email', 'email',
'start_date', 'start_date',
@@ -131,6 +135,18 @@ class Event extends InstancedModel
'swimming_permission_required' => 'boolean', 'swimming_permission_required' => 'boolean',
]; ];
/**
* Anschrift des Veranstaltungsorts in einer Zeile. Straße und Hausnummer sind optional -- fehlen sie,
* bleibt es bei der bisherigen Ausgabe "PLZ Ort".
*/
public function getFullAddress(): string
{
$city = trim($this->postal_code . ' ' . $this->location);
$street = trim($this->street . ' ' . $this->house_number);
return '' === $street ? $city : $street . ', ' . $city;
}
public function tenant(): BelongsTo public function tenant(): BelongsTo
{ {
return $this->belongsTo(Tenant::class, 'tenant', 'slug'); return $this->belongsTo(Tenant::class, 'tenant', 'slug');
@@ -109,6 +109,7 @@ class EventParticipantResource extends JsonResource
default => 'Nicht geprüft', default => 'Nicht geprüft',
}, },
'eventName' => $this->resource->event()->first()->name, 'eventName' => $this->resource->event()->first()->name,
'eventAddress' => $event->getFullAddress(),
'arrivalDateReadable' => $this->resource->arrival_date->format('d.m.Y'), 'arrivalDateReadable' => $this->resource->arrival_date->format('d.m.Y'),
'departureDateReadable' => $this->resource->departure_date->format('d.m.Y'), 'departureDateReadable' => $this->resource->departure_date->format('d.m.Y'),
'participationOptions' => $this->resource->selectedOptions()->get()->map( 'participationOptions' => $this->resource->selectedOptions()->get()->map(
+5
View File
@@ -30,7 +30,12 @@ class EventResource extends JsonResource{
'url' => 'https://' . currentTenant()->url . '/event/' . $this->event->identifier . '/signup', 'url' => 'https://' . currentTenant()->url . '/event/' . $this->event->identifier . '/signup',
'urlShort' => 'https://' . currentTenant()->url . '/event/' . $this->event->identifier, 'urlShort' => 'https://' . currentTenant()->url . '/event/' . $this->event->identifier,
'location' => $this->event->location, 'location' => $this->event->location,
'street' => $this->event->street,
'houseNumber' => $this->event->house_number,
'postalCode' => $this->event->postal_code, 'postalCode' => $this->event->postal_code,
// Fertig formatierte Anschrift für alle Anzeigen -- die Einzelfelder brauchen nur die
// Bearbeitungsformulare.
'fullAddress' => $this->event->getFullAddress(),
'email' => $this->event->email, 'email' => $this->event->email,
'accountOwner' => $this->event->account_owner, 'accountOwner' => $this->event->account_owner,
'accountIban' => $this->event->account_iban, 'accountIban' => $this->event->account_iban,
@@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Der Veranstaltungsort war bisher nur PLZ und Ort. Straße und Hausnummer kommen dazu, bleiben aber
* optional: Bestandsveranstaltungen haben sie nicht, und bei der Anlage sind sie oft noch unbekannt.
*/
public function up(): void
{
Schema::table('events', function (Blueprint $table) {
$table->string('street')->nullable()->after('location');
$table->string('house_number')->nullable()->after('street');
});
}
public function down(): void
{
Schema::table('events', function (Blueprint $table) {
$table->dropColumn(['street', 'house_number']);
});
}
};
+177
View File
@@ -0,0 +1,177 @@
<?php
namespace Tests\Feature;
use App\Domains\Event\Actions\CreateEvent\CreateEventCommand;
use App\Domains\Event\Actions\CreateEvent\CreateEventRequest;
use App\Domains\Event\Actions\UpdateEvent\UpdateEventCommand;
use App\Domains\Event\Actions\UpdateEvent\UpdateEventRequest;
use App\Enumerations\CostUnitType;
use App\Enumerations\EatingHabit;
use App\Enumerations\ParticipationFeeType;
use App\Models\CostUnit;
use App\Models\Event;
use App\Models\Tenant;
use App\Resources\EventResource;
use App\ValueObjects\Amount;
use DateTime;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
class EventAddressTest extends TestCase
{
use RefreshDatabase;
private Tenant $tenant;
protected function setUp(): void
{
parent::setUp();
$this->tenant = Tenant::create([
'slug' => 'tv',
'name' => 'Test',
'email' => 't@example.com',
'email_finance' => 'finance@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,
'tax_liable' => false,
'vat_rate' => 0,
'vat_pricing_mode' => 'inclusive',
]);
app()->instance('tenant', $this->tenant);
DB::table('cost_unit_types')->insert(['slug' => CostUnitType::COST_UNIT_TYPE_EVENT, 'name' => 'Veranstaltung']);
DB::table('participation_types')->insert(['slug' => 'participant', 'name' => 'Teilnehmer']);
DB::table('participation_fee_types')->insert(['slug' => 'fixed', 'name' => 'Fix']);
EatingHabit::create(['slug' => EatingHabit::EATING_HABIT_VEGAN, 'name' => 'Vegan']);
EatingHabit::create(['slug' => EatingHabit::EATING_HABIT_VEGETARIAN, 'name' => 'Vegetarisch']);
}
private function createEvent(?string $street = null, ?string $houseNumber = null): Event
{
$response = new CreateEventCommand(new CreateEventRequest(
name: 'Sommerlager',
location: 'Leipzig',
postalCode: '04103',
email: 'e@example.com',
begin: new DateTime('2026-09-01'),
end: new DateTime('2026-09-05'),
earlyBirdEnd: new DateTime('2026-08-20'),
registrationFinalEnd: new DateTime('2026-08-25'),
earlyBirdEndAmountIncrease: 0,
participationFeeType: ParticipationFeeType::where('slug', 'fixed')->first(),
accountOwner: 'Owner',
accountIban: 'DE00',
payPerDay: false,
street: $street,
houseNumber: $houseNumber,
))->execute();
$this->assertTrue($response->success);
return $response->event->fresh();
}
private function updateEvent(Event $event, ?string $street, ?string $houseNumber): Event
{
$response = new UpdateEventCommand(new UpdateEventRequest(
event: $event,
eventName: $event->name,
eventLocation: $event->location,
postalCode: $event->postal_code,
email: $event->email,
earlyBirdEnd: new DateTime('2026-08-20'),
registrationFinalEnd: new DateTime('2026-08-25'),
alcoholicsAge: 16,
sendWeeklyReports: true,
registrationAllowed: true,
flatSupport: Amount::fromString('0,00'),
supportPerPerson: Amount::fromString('0,00'),
contributingLocalGroups: [],
eatingHabits: [],
street: $street,
houseNumber: $houseNumber,
))->execute();
$this->assertTrue($response->success);
return $event->fresh();
}
public function test_anlage_speichert_strasse_und_hausnummer(): void
{
$event = $this->createEvent('Musterweg', '12');
$this->assertSame('Musterweg', $event->street);
$this->assertSame('12', $event->house_number);
}
public function test_anlage_ohne_angabe_laesst_beide_felder_leer(): void
{
$event = $this->createEvent();
$this->assertNull($event->street);
$this->assertNull($event->house_number);
}
public function test_leere_eingaben_werden_bei_der_anlage_zu_null(): void
{
$event = $this->createEvent('', ' ');
$this->assertNull($event->street);
$this->assertNull($event->house_number);
}
public function test_einstellungen_ergaenzen_und_leeren_die_anschrift(): void
{
$event = $this->updateEvent($this->createEvent(), 'Musterweg', '12');
$this->assertSame('Musterweg', $event->street);
$this->assertSame('12', $event->house_number);
$event = $this->updateEvent($event, '', '');
$this->assertNull($event->street);
$this->assertNull($event->house_number);
}
public function test_anschrift_enthaelt_strasse_nur_wenn_sie_gefuellt_ist(): void
{
$this->assertSame('Musterweg 12, 04103 Leipzig', $this->createEvent('Musterweg', '12')->getFullAddress());
$this->assertSame('04103 Leipzig', $this->createEvent()->getFullAddress());
}
public function test_resource_liefert_einzelfelder_und_fertige_anschrift(): void
{
$event = $this->createEvent('Musterweg', '12');
// Die Resource gibt auch die Kostenstelle aus; im Betrieb legt der Controller sie direkt nach
// der Veranstaltung an.
$event->cost_unit_id = 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,
])->id;
$event->save();
$resource = new EventResource($event)->toArray(new Request());
$this->assertSame('Musterweg', $resource['street']);
$this->assertSame('12', $resource['houseNumber']);
$this->assertSame('Musterweg 12, 04103 Leipzig', $resource['fullAddress']);
}
}