Skip to content

Latest commit

 

History

History
68 lines (58 loc) · 1.61 KB

File metadata and controls

68 lines (58 loc) · 1.61 KB

Domain Model

Entities

Event

  • id: UUID
  • title: string
  • totalSeats: int
  • startsAt: DateTimeImmutable

Seat

  • id: UUID
  • eventId: UUID
  • rowName: string
  • seatNumber: int
  • status: SeatStatus (AVAILABLE | LOCKED | SOLD) – backed string enum
  • priceCents: int (EUR default)
  • reservationId: UUID|null

Reservation

  • id: UUID
  • userId: UUID (ValueObject\UserId)
  • status: ReservationStatus (PENDING | PAID | CANCELLED | EXPIRED)
  • expiresAt: DateTimeImmutable (15 minutes from creation)
  • totalAmountCents: int
  • seats: OneToMany Seat

Value Objects

  • Money(amount: int, currency: 'EUR')
  • UserId(string $value) – validates UUID v4 on construct

Business Rules (Immutable)

  • Maximum 5 seats per reservation
  • Reservation TTL: exactly 900 seconds (15 minutes) from creation
  • Currency: always EUR, stored as cents (int)
  • Money Value Object: Domain\ValueObject\Money
    • Immutable
    • Always positive
    • Methods: add(Money $other): Money, equals(Money $other): bool, toCents(): int
  • UserId Value Object: Domain\ValueObject\UserId
    • Validates UUID v4 on construction
    • Always stored lowercase
  • SeatStatus and ReservationStatus: backed string enums (PHP 8.1+)

Domain Events (dispatched to Messenger/outbox)

ReservationCreated

{
  "reservationId": "uuid",
  "userId": "uuid",
  "eventId": "uuid",
  "seatIds": ["uuid", "..."],
  "expiresAt": "2025-11-22T10:15:00+00:00",
  "totalAmount": 15000,
  "occurredOn": "2025-11-22T10:00:00+00:00"
}

ReservationExpired

{
  "reservationId": "uuid",
  "reason": "TIMEOUT",
  "occurredOn": "2025-11-22T10:15:01+00:00"
}