Reservation.java
package cl.prgm.portaltrip.domain.model;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.UUID;
import cl.prgm.portaltrip.domain.exception.DomainValidationException;
import cl.prgm.portaltrip.domain.exception.InvalidReservationStateException;
public record Reservation(
UUID id,
UUID userId,
UUID idempotencyKey,
String number,
ReservationStatus status,
String passengerName,
String email,
Integer destinationId,
LocalDate travelDate,
int passengers,
List<Integer> companionIds,
TripType tripType,
boolean insurance,
String comments,
Quote quote,
OffsetDateTime createdAt,
OffsetDateTime startedAt,
OffsetDateTime completedAt) {
public Reservation {
companionIds = List.copyOf(companionIds);
}
public static Reservation confirm(
ReservationDraft draft,
UUID userId,
String email,
UUID idempotencyKey,
Location destination,
List<Character> companions,
Quote quote,
UUID id,
String number,
OffsetDateTime createdAt) {
if (companions.stream().anyMatch(companion -> !companion.isAlive())) {
throw new DomainValidationException("Every selected companion must be alive.");
}
if (destination.requiresInterdimensionalInsurance() && !draft.insurance()) {
throw new DomainValidationException(
"Destinations in an unknown dimension require interdimensional insurance.");
}
return new Reservation(
id,
userId,
idempotencyKey,
number,
ReservationStatus.CONFIRMED,
draft.passengerName(),
email,
destination.id(),
draft.travelDate(),
draft.passengers(),
draft.companionIds(),
draft.tripType(),
draft.insurance(),
draft.comments(),
quote,
createdAt,
null,
null);
}
public Reservation start(OffsetDateTime now) {
if (status != ReservationStatus.CONFIRMED) {
throw new InvalidReservationStateException(number, status, ReservationStatus.IN_PROGRESS);
}
return transitionTo(ReservationStatus.IN_PROGRESS, now, completedAt);
}
public Reservation complete(OffsetDateTime now) {
if (status != ReservationStatus.IN_PROGRESS) {
throw new InvalidReservationStateException(number, status, ReservationStatus.COMPLETED);
}
return transitionTo(ReservationStatus.COMPLETED, startedAt, now);
}
public Reservation cancel() {
if (status != ReservationStatus.CONFIRMED) {
throw new InvalidReservationStateException(number, status, ReservationStatus.CANCELLED);
}
return transitionTo(ReservationStatus.CANCELLED, startedAt, completedAt);
}
private Reservation transitionTo(
ReservationStatus newStatus,
OffsetDateTime newStartedAt,
OffsetDateTime newCompletedAt) {
return new Reservation(
id,
userId,
idempotencyKey,
number,
newStatus,
passengerName,
email,
destinationId,
travelDate,
passengers,
companionIds,
tripType,
insurance,
comments,
quote,
createdAt,
newStartedAt,
newCompletedAt);
}
public boolean matches(ReservationDraft draft) {
return passengerName.equals(draft.passengerName())
&& destinationId.equals(draft.destinationId())
&& travelDate.equals(draft.travelDate())
&& passengers == draft.passengers()
&& companionIds.equals(draft.companionIds())
&& tripType == draft.tripType()
&& insurance == draft.insurance()
&& comments.equals(draft.comments());
}
}