A movie ticket booking site lists all the theaters from different theater chains, e.g. PVR, INOX, Cinepolis etc.
Implement a Movie Ticket Booking Application for a Theatre. Refer to the following details:
- A Theatre has Screens that run Shows for different Movies. Each Show has a particular Movie, start time, duration, and is played in a particular Screen in the theatre. Each Screen has an arrangement of Seats that can be booked by Users.
- Assume all Users are registered, authenticated, and logged in to the Application.
- Once a User selects a particular show to book tickets for, a UserBookingSession starts. Within this UserBookingSession, a User will be able to get the Available Seats for the show and select the Seats he wishes to book. It is a ‘good to have’ for the Application to have limits on the number of seats a User can book in a Ticket.
- Once the user has selected a group of seats, these seats should become TEMPORARILY_UNAVAILABLE to all other Users.
- The User then proceeds to make payment which can either be SUCCESS or FAILURE.
- If Payment FAILED, user can retry Payment for a maximum number of times. Beyond maximum retries, the seats are made AVAILABLE.
- If Payment SUCCEEDS, Ticket or Booking Confirmation is generated and made available to the User. The UserBookingSession is closed and the Seats are made PERMANENTLY_UNAVAILABLE.
- A User can also explicitly close the UserBookingSession after selecting seats and before making payment. In this case, the seats selected are made AVAILABLE once again.
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public class Movie {
private final String id;
private final String name;
private int durationInMins;
private String genre;
//Other metadata
}
import lombok.Getter;
import lombok.NonNull;
import java.util.ArrayList;
import java.util.List;
@Getter
public class CinemaHall {
private final String id;
private final String name;
private final List<Screen> screens;
//Other theatre metadata.
public CinemaHall(@NonNull final String id, @NonNull final String name) {
this.id = id;
this.name = name;
this.screens = new ArrayList<>();
}
public void addScreen(@NonNull final Screen screen) {
screens.add(screen);
}
}
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import javax.management.MXBean;
import java.util.ArrayList;
import java.util.List;
@Getter
public class Screen {
private final String id;
private final String name;
private final CinemaHall theatre;
//Other screen metadata.
private final List<Show> shows;
public Screen(@NonNull final String id, @NonNull final String name, @NonNull final CinemaHall theatre) {
this.id = id;
this.name = name;
this.theatre = theatre;
this.seats = new ArrayList<>();
}
public void addSeat(@NonNull final Seat seat) {
this.seats.add(seat);
}
}
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Date;
@AllArgsConstructor
@Getter
public class Show {
private final String showId;
private final Movie movie;
private final Screen screen;
private final Date startTime;
private final Integer durationInSeconds;
}
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public class Seat {
private final String id;
private final int rowNo;
private final int seatNo;
private SeatType seatType; // Silver, Gold, Diamond
}
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.time.Instant;
import java.util.Date;
@AllArgsConstructor
@Getter
public class SeatLock {
private Seat seat;
private Show show;
private Integer timeoutInSeconds;
private Date lockTime;
private String lockedBy;
public boolean isLockExpired() {
final Instant lockInstant = lockTime.toInstant().plusSeconds(timeoutInSeconds);
final Instant currentInstant = new Date().toInstant();
return lockInstant.isBefore(currentInstant);
}
}
import lombok.Getter;
import lombok.NonNull;
import java.util.List;
@Getter
public class Booking {
private final String bookingId;
private final String userId;
private BookingStatus bookingStatus;
private final List<Seat> seatsBooked;
private final Show show;
public Booking(@NonNull final String id, @NonNull final Show show, @NonNull final String user,
@NonNull final List<Seat> seatsBooked) {
this.id = id;
this.show = show;
this.seatsBooked = seatsBooked;
this.user = user;
this.bookingStatus = BookingStatus.Created;
}
public boolean isConfirmed() {
return this.bookingStatus == BookingStatus.Confirmed;
}
public void confirmBooking() {
if (this.bookingStatus != BookingStatus.Created) {
throw new InvalidStateException();
}
this.bookingStatus = BookingStatus.Confirmed;
}
public void expireBooking() {
if (this.bookingStatus != BookingStatus.Created) {
throw new InvalidStateException();
}
this.bookingStatus = BookingStatus.Expired;
}
}
public enum BookingStatus {
REQUESTED, PENDING, CONFIRMED, CANCELLED;
}