Allows guests to cancel their RSVP via a DELETE endpoint using their guestToken. Frontend shows cancel button in RsvpBar and clears local storage on success. Includes unit tests, integration tests, and E2E spec. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2.4 KiB
2.4 KiB
Data Model: Cancel RSVP
Feature: 014-cancel-rsvp | Date: 2026-03-09
Entities
RSVP (existing — no schema changes)
| Field | Type | Constraints | Notes |
|---|---|---|---|
| id | BIGSERIAL | PK, auto-generated | Internal DB ID, never exposed |
| rsvp_token | UUID | UNIQUE, NOT NULL | Bearer credential for the guest |
| event_id | BIGINT | FK → events.id, NOT NULL | Links RSVP to event |
| name | VARCHAR(100) | NOT NULL | Guest display name |
No migration needed. The cancel feature only deletes existing rows — no new columns or tables.
State Transitions
┌──────────┐ POST /events/{token}/rsvps ┌──────────┐
│ No RSVP │ ──────────────────────────────► │ Attending │
│ (guest) │ ◄────────────────────────────── │ (guest) │
└──────────┘ DELETE /events/{token}/rsvps/ └──────────┘
{rsvpToken}
The transition is fully reversible: after cancellation, the guest can create a new RSVP (new token generated).
Client-Side Storage (localStorage)
StoredEvent (existing interface — no changes)
interface StoredEvent {
eventToken: string // always present
title: string // always present
dateTime: string // always present
organizerToken?: string // present if organizer
rsvpToken?: string // present if RSVP'd — CLEARED on cancel
rsvpName?: string // present if RSVP'd — CLEARED on cancel
}
Cancel Effects on localStorage
| Action | rsvpToken | rsvpName | Event in list |
|---|---|---|---|
| Cancel from detail view | Removed | Removed | Kept |
| Remove from event list | Removed | Removed | Removed |
Repository Changes
RsvpRepository (domain port)
New method:
/**
* Delete an RSVP by event ID and RSVP token.
* @return true if a record was deleted, false if not found
*/
boolean deleteByEventIdAndRsvpToken(Long eventId, RsvpToken rsvpToken);
RsvpJpaRepository
New method:
long deleteByEventIdAndRsvpToken(Long eventId, UUID rsvpToken);
Returns count of deleted rows (0 or 1). Spring Data JPA auto-implements this derived query.