Add RSVP creation endpoint with typed tokens and attendee count

Introduce typed token value objects (EventToken, OrganizerToken,
RsvpToken) and refactor all existing Event code to use them.

Add POST /events/{token}/rsvps endpoint that persists an RSVP and
returns an rsvpToken. Populate attendeeCount in GET /events/{token}
from a real count query instead of hardcoded 0.

Includes: OpenAPI spec, Liquibase migration (rsvps table with
ON DELETE CASCADE), domain model, hexagonal ports/adapters,
service layer, and full test coverage (unit + integration).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 11:49:49 +01:00
parent 4828d06aba
commit a625e34fe4
24 changed files with 688 additions and 39 deletions
@@ -9,6 +9,7 @@ import static org.mockito.Mockito.when;
import de.fete.domain.model.CreateEventCommand;
import de.fete.domain.model.Event;
import de.fete.domain.model.EventToken;
import de.fete.domain.port.out.EventRepository;
import java.time.Clock;
import java.time.Instant;
@@ -17,7 +18,6 @@ import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Optional;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -130,7 +130,7 @@ class EventServiceTest {
@Test
void getByEventTokenReturnsEvent() {
UUID token = UUID.randomUUID();
EventToken token = EventToken.generate();
var event = new Event();
event.setEventToken(token);
event.setTitle("Found Event");
@@ -145,7 +145,7 @@ class EventServiceTest {
@Test
void getByEventTokenReturnsEmptyForUnknownToken() {
UUID token = UUID.randomUUID();
EventToken token = EventToken.generate();
when(eventRepository.findByEventToken(token))
.thenReturn(Optional.empty());