diff --git a/.gitignore b/.gitignore index dc01f204..660ee6a8 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,6 @@ out/ ### VS Code ### .vscode/ + +src/main/resources/application.yml + diff --git a/build.gradle b/build.gradle index 3d7f7607..5a4443e1 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' developmentOnly 'org.springframework.boot:spring-boot-devtools' - runtimeOnly 'org.postgresql:postgresql' + implementation 'org.postgresql:postgresql:42.7.3' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } diff --git a/src/main/java/com/booleanuk/api/cinema/Main.java b/src/main/java/com/booleanuk/api/cinema/Main.java new file mode 100644 index 00000000..c4fb60ea --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/Main.java @@ -0,0 +1,11 @@ +package com.booleanuk.api.cinema; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Main { + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/controllers/CustomerController.java b/src/main/java/com/booleanuk/api/cinema/controllers/CustomerController.java new file mode 100644 index 00000000..0e52624c --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/controllers/CustomerController.java @@ -0,0 +1,94 @@ +package com.booleanuk.api.cinema.controllers; + +import com.booleanuk.api.cinema.models.Customer; +import com.booleanuk.api.cinema.repository.CustomerRepository; +import com.booleanuk.api.cinema.response.CustomerListResponse; +import com.booleanuk.api.cinema.response.CustomerResponse; +import com.booleanuk.api.cinema.response.ErrorResponse; +import com.booleanuk.api.cinema.response.Response; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.util.List; + +@RestController +@RequestMapping("customers") +public class CustomerController { + + private CustomerListResponse customerListResponse = new CustomerListResponse(); + private CustomerResponse customerResponse = new CustomerResponse(); + + @Autowired + private CustomerRepository customerRepository; + + @GetMapping + public ResponseEntity> getAllCustomers () { + List customers = customerRepository.findAll(); + this.customerListResponse.set(customers); + + return ResponseEntity.ok(customerListResponse); + } + + @PostMapping + public ResponseEntity> createCustomer(@RequestBody Customer customer){ + + if (customer.getName() == null || customer.getEmail() == null || customer.getPhone() == null){ + ErrorResponse error = new ErrorResponse(); + error.set("Could not create a new customer, please check all fields are correct"); + + return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + } + + customer.setCreatedAt(LocalDateTime.now()); + customer.setUpdatedAt(LocalDateTime.now()); + this.customerResponse.set(customer); + this.customerRepository.save(customer); + + return new ResponseEntity<>(customerResponse, HttpStatus.CREATED); + } + + @PutMapping("{id}") + public ResponseEntity> updateCustomer(@PathVariable int id, @RequestBody Customer customer){ + + if (customer.getName() == null || customer.getEmail() == null || customer.getPhone() == null){ + ErrorResponse error = new ErrorResponse(); + error.set("Could not create a new customer, please check all fields are correct"); + return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + } + + Customer customerToUpdate = customerRepository.findById(id).orElse(null); + if(customerToUpdate == null){ + ErrorResponse error = new ErrorResponse(); + error.set("No customer with that ID found"); + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } + + customerToUpdate.setName(customer.getName()); + customerToUpdate.setEmail(customer.getEmail()); + customerToUpdate.setPhone(customer.getPhone()); + customerToUpdate.setUpdatedAt(LocalDateTime.now()); + this.customerResponse.set(customerToUpdate); + this.customerRepository.save(customerToUpdate); + + return new ResponseEntity<>(customerResponse, HttpStatus.CREATED); + } + + @DeleteMapping("{id}") + public ResponseEntity> deleteCustomer(@PathVariable int id){ + + Customer customerToDelete = this.customerRepository.findById(id).orElse(null); + if (customerToDelete == null){ + ErrorResponse error = new ErrorResponse(); + error.set("No customer with that ID found"); + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } + + this.customerResponse.set(customerToDelete); + this.customerRepository.delete(customerToDelete); + + return ResponseEntity.ok(customerResponse); + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/controllers/MovieController.java b/src/main/java/com/booleanuk/api/cinema/controllers/MovieController.java new file mode 100644 index 00000000..bf94fcfb --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/controllers/MovieController.java @@ -0,0 +1,97 @@ +package com.booleanuk.api.cinema.controllers; + +import com.booleanuk.api.cinema.models.Movie; +import com.booleanuk.api.cinema.repository.MovieRepository; +import com.booleanuk.api.cinema.repository.ScreeningRepository; +import com.booleanuk.api.cinema.response.ErrorResponse; +import com.booleanuk.api.cinema.response.MovieListResponse; +import com.booleanuk.api.cinema.response.MovieResponse; +import com.booleanuk.api.cinema.response.Response; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.util.List; + +@RestController +@RequestMapping("movies") +public class MovieController { + + @Autowired + private MovieRepository movieRepository; + + @Autowired + private ScreeningRepository screeningRepository; + + private MovieResponse movieResponse = new MovieResponse(); + private MovieListResponse movieListResponse = new MovieListResponse(); + + @GetMapping + public ResponseEntity> getAllMovies(){ + List movies = this.movieRepository.findAll(); + this.movieListResponse.set(movies); + + return ResponseEntity.ok(movieListResponse); + } + + @PostMapping + public ResponseEntity> createMovie(@RequestBody Movie movie){ + if (movie.getTitle() == null || movie.getRating() == null || movie.getDescription() == null || movie.getRuntimeMins() <= 0){ + ErrorResponse error = new ErrorResponse(); + error.set("Could not create a new movie, please check all fields are correct"); + return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + } + + movie.setCreatedTime(LocalDateTime.now()); + movie.setUpdatedTime(LocalDateTime.now()); + + this.movieRepository.save(movie); + this.movieResponse.set(movie); + + return new ResponseEntity<>(movieResponse, HttpStatus.CREATED); + } + + @PutMapping("{id}") + public ResponseEntity> updateMovie(@PathVariable int id, @RequestBody Movie movie){ + if (movie.getTitle() == null || movie.getRating() == null || movie.getDescription() == null || movie.getRuntimeMins() <= 0){ + ErrorResponse error = new ErrorResponse(); + error.set("Could not create a new movie, please check all fields are correct"); + return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + } + + Movie movieToUpdate = this.movieRepository.findById(id).orElse(null); + if (movieToUpdate == null){ + ErrorResponse error = new ErrorResponse(); + error.set("No movie with that id found"); + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } + + movieToUpdate.setTitle(movie.getTitle()); + movieToUpdate.setRating(movie.getRating()); + movieToUpdate.setDescription(movie.getDescription()); + movieToUpdate.setRuntimeMins(movie.getRuntimeMins()); + + this.movieRepository.save(movieToUpdate); + this.movieResponse.set(movieToUpdate); + + return new ResponseEntity<>(movieResponse, HttpStatus.CREATED); + } + + @DeleteMapping("{id}") + public ResponseEntity> deleteMovie(@PathVariable int id){ + Movie movieToDelete = this.movieRepository.findById(id).orElse(null); + if (movieToDelete == null){ + ErrorResponse error = new ErrorResponse(); + error.set("No movie with that id found"); + + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } + + this.movieRepository.delete(movieToDelete); + this.movieResponse.set(movieToDelete); + + return ResponseEntity.ok(movieResponse); + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/controllers/ScreeningController.java b/src/main/java/com/booleanuk/api/cinema/controllers/ScreeningController.java new file mode 100644 index 00000000..b9b8569a --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/controllers/ScreeningController.java @@ -0,0 +1,80 @@ +package com.booleanuk.api.cinema.controllers; + +import com.booleanuk.api.cinema.models.Movie; +import com.booleanuk.api.cinema.models.Screening; +import com.booleanuk.api.cinema.repository.MovieRepository; +import com.booleanuk.api.cinema.repository.ScreeningRepository; +import com.booleanuk.api.cinema.repository.TicketRepository; +import com.booleanuk.api.cinema.response.ErrorResponse; +import com.booleanuk.api.cinema.response.Response; +import com.booleanuk.api.cinema.response.ScreeningListResponse; +import com.booleanuk.api.cinema.response.ScreeningResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.util.List; + +@RestController +@RequestMapping("movies/{id}/screenings") +public class ScreeningController { + + @Autowired + private ScreeningRepository screeningRepository; + + @Autowired + private MovieRepository movieRepository; + + @Autowired + private TicketRepository ticketRepository; + + private ScreeningResponse screeningResponse = new ScreeningResponse(); + private ScreeningListResponse screeningListResponse = new ScreeningListResponse(); + + @GetMapping + public ResponseEntity> getAllScreening(@PathVariable int id) { + Movie movie = this.movieRepository.findById(id).orElse(null); + if (movie == null){ + ErrorResponse error = new ErrorResponse(); + error.set("No movie with that id found"); + + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } + + List screeningsList = this.screeningRepository.findByMovie(movie); + this.screeningListResponse.set(screeningsList); + + return ResponseEntity.ok(screeningListResponse); + } + + @PostMapping + public ResponseEntity> createScreening(@PathVariable int id, @RequestBody Screening screening){ + if (screening.getScreenNumber() <= 0 || screening.getCapacity() <= 0 || screening.getStartsAt() == null){ + ErrorResponse error = new ErrorResponse(); + error.set("Could not create a screening for the specified movie, please check all fields are correct"); + + return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + } + + Movie movie = this.movieRepository.findById(id).orElse(null); + if (movie == null){ + ErrorResponse error = new ErrorResponse(); + error.set("No movie with that id found"); + + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } + + screening.setMovie(movie); + screening.setCreatedAt(LocalDateTime.now()); + screening.setUpdatedAt(LocalDateTime.now()); + movie.addScreening(screening); + + this.screeningRepository.save(screening); + this.screeningResponse.set(screening); + + return new ResponseEntity<>(screeningResponse, HttpStatus.CREATED); + } + +} diff --git a/src/main/java/com/booleanuk/api/cinema/controllers/TicketController.java b/src/main/java/com/booleanuk/api/cinema/controllers/TicketController.java new file mode 100644 index 00000000..34e863c9 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/controllers/TicketController.java @@ -0,0 +1,85 @@ +package com.booleanuk.api.cinema.controllers; + +import com.booleanuk.api.cinema.models.Customer; +import com.booleanuk.api.cinema.models.Screening; +import com.booleanuk.api.cinema.models.Ticket; +import com.booleanuk.api.cinema.repository.CustomerRepository; +import com.booleanuk.api.cinema.repository.ScreeningRepository; +import com.booleanuk.api.cinema.repository.TicketRepository; +import com.booleanuk.api.cinema.response.ErrorResponse; +import com.booleanuk.api.cinema.response.Response; +import com.booleanuk.api.cinema.response.TicketListResponse; +import com.booleanuk.api.cinema.response.TicketResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.util.List; + +@RestController +@RequestMapping("customers") +public class TicketController { + + @Autowired + private TicketRepository ticketRepository; + + @Autowired + private ScreeningRepository screeningRepository; + + @Autowired + private CustomerRepository customerRepository; + + private TicketResponse ticketResponse = new TicketResponse(); + private TicketListResponse ticketListResponse = new TicketListResponse(); + + @PostMapping("{customerId}/screenings/{screeningId}") + public ResponseEntity> createTicket(@PathVariable(name = "customerId") int customerId, @PathVariable(name = "screeningId") int screeningId, @RequestBody Ticket ticket){ + + Customer customer = this.customerRepository.findById(customerId).orElse(null); + Screening screening = this.screeningRepository.findById(screeningId).orElse(null); + + if (customer == null || screening == null){ + ErrorResponse error = new ErrorResponse(); + error.set("No customer or screening with those ids found"); + + new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } + + ticket.setCustomer(customer); + ticket.setScreening(screening); + ticket.setCreatedAt(LocalDateTime.now()); + ticket.setUpdatedAt(LocalDateTime.now()); + + this.ticketRepository.save(ticket); + this.ticketResponse.set(ticket); + + return new ResponseEntity<>(ticketResponse, HttpStatus.CREATED); + } + + @GetMapping("{customerId}/screenings/{screeningId}") + public ResponseEntity> getAllTickets (@PathVariable(name = "customerId") int customerId, @PathVariable(name = "screeningId") int screeningId){ + + Customer customer = this.customerRepository.findById(customerId).orElse(null); + Screening screening = this.screeningRepository.findById(screeningId).orElse(null); + if (customer == null || screening == null){ + ErrorResponse error = new ErrorResponse(); + error.set("No customer or screening with those ids found"); + + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } + + List ticketList = this.ticketRepository.findAllByCustomerIdAndScreeningId(customer.getId(), screening.getId()); + if (ticketList.isEmpty()){ + ErrorResponse error = new ErrorResponse(); + error.set("No ticket found for the customer and screening with those ids found"); + + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } + + this.ticketListResponse.set(ticketList); + return ResponseEntity.ok(ticketListResponse); + } + +} diff --git a/src/main/java/com/booleanuk/api/cinema/dto/MovieDto.java b/src/main/java/com/booleanuk/api/cinema/dto/MovieDto.java new file mode 100644 index 00000000..8f0b6498 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/dto/MovieDto.java @@ -0,0 +1,81 @@ +package com.booleanuk.api.cinema.dto; + +import com.booleanuk.api.cinema.models.Movie; + +import java.time.LocalDateTime; + +public class MovieDto { + private int id; + private String title; + private String rating; + private String description; + private int runtimeMins; + private LocalDateTime createdAt; + private LocalDateTime updatedAt; + + public MovieDto(Movie movie) { + this.id = movie.getId(); + this.title = movie.getTitle(); + this.rating = movie.getRating(); + this.description = movie.getDescription(); + this.runtimeMins = movie.getRuntimeMins(); + this.createdAt = movie.getCreatedTime(); + this.updatedAt = movie.getUpdatedTime(); + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getRating() { + return rating; + } + + public void setRating(String rating) { + this.rating = rating; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public int getRuntimeMins() { + return runtimeMins; + } + + public void setRuntimeMins(int runtimeMins) { + this.runtimeMins = runtimeMins; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/dto/ScreeningDto.java b/src/main/java/com/booleanuk/api/cinema/dto/ScreeningDto.java new file mode 100644 index 00000000..25b9301b --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/dto/ScreeningDto.java @@ -0,0 +1,41 @@ +package com.booleanuk.api.cinema.dto; + +import com.booleanuk.api.cinema.models.Screening; + +import java.time.LocalDateTime; + +public class ScreeningDto { + private int screenNumber; + private int capacity; + private LocalDateTime statsAt; + + public ScreeningDto(Screening screening) { + this.screenNumber = screening.getScreenNumber(); + this.capacity = screening.getCapacity(); + this.statsAt = screening.getStartsAt(); + } + + public int getScreenNumber() { + return screenNumber; + } + + public void setScreenNumber(int screenNumber) { + this.screenNumber = screenNumber; + } + + public int getCapacity() { + return capacity; + } + + public void setCapacity(int capacity) { + this.capacity = capacity; + } + + public LocalDateTime getStatsAt() { + return statsAt; + } + + public void setStatsAt(LocalDateTime statsAt) { + this.statsAt = statsAt; + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/dto/TicketDto.java b/src/main/java/com/booleanuk/api/cinema/dto/TicketDto.java new file mode 100644 index 00000000..b5a5048e --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/dto/TicketDto.java @@ -0,0 +1,59 @@ +package com.booleanuk.api.cinema.dto; + +import com.booleanuk.api.cinema.models.Ticket; + +public class TicketDto { + private int customerId; + private String name; + private int screeningId; + private String title; + private int numSeats; + + public TicketDto(Ticket ticket) { + this.customerId = ticket.getCustomer().getId(); + this.name = ticket.getCustomer().getName(); + this.screeningId = ticket.getScreening().getId(); + this.title = ticket.getScreening().getMovie().getTitle(); + this.numSeats = ticket.getNumSeats(); + } + + public int getCustomerId() { + return customerId; + } + + public void setCustomerId(int customerId) { + this.customerId = customerId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getScreeningId() { + return screeningId; + } + + public void setScreeningId(int screeningId) { + this.screeningId = screeningId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getNumSeats() { + return numSeats; + } + + public void setNumSeats(int numSeats) { + this.numSeats = numSeats; + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/models/Customer.java b/src/main/java/com/booleanuk/api/cinema/models/Customer.java new file mode 100644 index 00000000..74d9761a --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/models/Customer.java @@ -0,0 +1,100 @@ +package com.booleanuk.api.cinema.models; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.persistence.*; + +import java.time.LocalDateTime; +import java.util.List; + +@Entity +@Table(name = "customers") +public class Customer { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @OneToMany(mappedBy = "customer") + @JsonIgnoreProperties("customer") + private List tickets; + + @Column(name = "name") + private String name; + + @Column(name = "email") + private String email; + + @Column(name = "phone") + private String phone; + + @Column(name = "created_at") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createdAt; + + @Column(name = "updated_at") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updatedAt; + + public Customer(){ + } + + public Customer(int id){ + this.id = id; + } + + public Customer(int id, String name, String email, String phone, LocalDateTime createdAt, LocalDateTime updatedAt){ + this.id = id; + this.name = name; + this.email = email; + this.phone = phone; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/models/Movie.java b/src/main/java/com/booleanuk/api/cinema/models/Movie.java new file mode 100644 index 00000000..3e05da4c --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/models/Movie.java @@ -0,0 +1,125 @@ +package com.booleanuk.api.cinema.models; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.persistence.*; + +import java.time.LocalDateTime; +import java.util.List; + +@Entity +@Table(name = "movies") +public class Movie { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @Column(name = "title") + private String title; + + @Column(name = "rating") + private String rating; + + @Column(name = "description") + private String description; + + @Column(name = "run_time_mins") + private int runtimeMins; + + @Column(name = "created_at") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createdTime; + + @Column(name = "updated_at") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updatedTime; + + @OneToMany(mappedBy = "movie", fetch = FetchType.EAGER) + @JsonIgnoreProperties("movie") + private List screenings; + + + public Movie(){ + + } + + public Movie(int id){ + this.id = id; + } + + public Movie(String title, String rating, String description, int runtimeMins){ + this.title = title; + this.rating = rating; + this.description = description; + this.runtimeMins = runtimeMins; + } + + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getRating() { + return rating; + } + + public void setRating(String rating) { + this.rating = rating; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public int getRuntimeMins() { + return runtimeMins; + } + + public void setRuntimeMins(int runtimeMins) { + this.runtimeMins = runtimeMins; + } + + public LocalDateTime getCreatedTime() { + return createdTime; + } + + public void setCreatedTime(LocalDateTime createdTime) { + this.createdTime = createdTime; + } + + public LocalDateTime getUpdatedTime() { + return updatedTime; + } + + public void setUpdatedTime(LocalDateTime updatedTime) { + this.updatedTime = updatedTime; + } + + public List getScreenings() { + return screenings; + } + + public void setScreenings(List screenings) { + this.screenings = screenings; + } + + public void addScreening(Screening screening){ + this.screenings.add(screening); + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/models/Screening.java b/src/main/java/com/booleanuk/api/cinema/models/Screening.java new file mode 100644 index 00000000..1c49db39 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/models/Screening.java @@ -0,0 +1,129 @@ +package com.booleanuk.api.cinema.models; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonIncludeProperties; +import jakarta.persistence.*; + +import java.time.LocalDateTime; +import java.util.List; + +@Entity +@Table(name = "screenings") +public class Screening { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @ManyToOne + @JoinColumn(name = "movie_id", nullable = false) + @JsonIncludeProperties(value = {"title", "rating", "description", "run_time_mins", "created_at", "updated_at"}) + private Movie movie; + + @OneToMany(mappedBy = "screening") + @JsonIgnoreProperties("screening") + private List tickets; + + @Column(name = "screen_number") + private int screenNumber; + + @Column(name = "starts_at") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime startsAt; + + @Column(name = "capacity") + private int capacity; + + @Column(name = "created_at") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createdAt; + + @Column(name = "updated_at") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updatedAt; + + public Screening() { + } + + public Screening(int id) { + this.id = id; + } + + public Screening(int screenNumber, LocalDateTime startsAt, int capacity) { + this.capacity = capacity; + this.screenNumber = screenNumber; + this.startsAt = startsAt; + } + + public Screening(int id, int screenNumber, LocalDateTime startsAt, int capacity) { + this.id = id; + this.screenNumber = screenNumber; + this.startsAt = startsAt; + this.capacity = capacity; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public LocalDateTime getStartsAt() { + return startsAt; + } + + public void setStartsAt(LocalDateTime startsAt) { + this.startsAt = startsAt; + } + + public int getCapacity() { + return capacity; + } + + public void setCapacity(int capacity) { + this.capacity = capacity; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } + + public Movie getMovie() { + return movie; + } + + public void setMovie(Movie movie) { + this.movie = movie; + } + + public int getScreenNumber() { + return screenNumber; + } + + public void setScreenNumber(int screenNumber) { + this.screenNumber = screenNumber; + } + + public List getTickets() { + return tickets; + } + + public void setTickets(List tickets) { + this.tickets = tickets; + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/models/Ticket.java b/src/main/java/com/booleanuk/api/cinema/models/Ticket.java new file mode 100644 index 00000000..a061e43b --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/models/Ticket.java @@ -0,0 +1,99 @@ +package com.booleanuk.api.cinema.models; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIncludeProperties; +import jakarta.persistence.*; +import java.time.LocalDateTime; + +@Entity +@Table(name = "tickets") +public class Ticket { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @ManyToOne + @JoinColumn(name = "customer_id", nullable = false) + @JsonIncludeProperties(value = {"name", "email", "phone", "created_at", "updated_at"}) + private Customer customer; + + @ManyToOne + @JoinColumn(name = "screening_id", nullable = false) + @JsonIncludeProperties(value = {"movie_id", "screen_number", "starts_at", "capacity", "created_at", "updated_at"}) + private Screening screening; + + @Column(name = "num_seats") + private int numSeats; + + @Column(name = "created_at") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createdAt; + + @Column(name = "updated_at") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updatedAt; + + public Ticket() { + } + + public Ticket(int numSeats){ + this.numSeats = numSeats; + } + + public Ticket(Customer customer, Screening screening, int numSeats, LocalDateTime createdAt, LocalDateTime updatedAt) { + this.customer = customer; + this.screening = screening; + this.numSeats = numSeats; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(Customer customer) { + this.customer = customer; + } + + public Screening getScreening() { + return screening; + } + + public void setScreening(Screening screening) { + this.screening = screening; + } + + public int getNumSeats() { + return numSeats; + } + + public void setNumSeats(int numSeats) { + this.numSeats = numSeats; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/repository/CustomerRepository.java b/src/main/java/com/booleanuk/api/cinema/repository/CustomerRepository.java new file mode 100644 index 00000000..e69f07f0 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/repository/CustomerRepository.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.cinema.repository; + +import com.booleanuk.api.cinema.models.Customer; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CustomerRepository extends JpaRepository { +} diff --git a/src/main/java/com/booleanuk/api/cinema/repository/MovieRepository.java b/src/main/java/com/booleanuk/api/cinema/repository/MovieRepository.java new file mode 100644 index 00000000..c6041f12 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/repository/MovieRepository.java @@ -0,0 +1,8 @@ +package com.booleanuk.api.cinema.repository; + +import com.booleanuk.api.cinema.models.Movie; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MovieRepository extends JpaRepository { + +} diff --git a/src/main/java/com/booleanuk/api/cinema/repository/ScreeningRepository.java b/src/main/java/com/booleanuk/api/cinema/repository/ScreeningRepository.java new file mode 100644 index 00000000..3c4d5bee --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/repository/ScreeningRepository.java @@ -0,0 +1,11 @@ +package com.booleanuk.api.cinema.repository; + +import com.booleanuk.api.cinema.models.Movie; +import com.booleanuk.api.cinema.models.Screening; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface ScreeningRepository extends JpaRepository { + List findByMovie(Movie movie); +} diff --git a/src/main/java/com/booleanuk/api/cinema/repository/TicketRepository.java b/src/main/java/com/booleanuk/api/cinema/repository/TicketRepository.java new file mode 100644 index 00000000..6e737499 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/repository/TicketRepository.java @@ -0,0 +1,11 @@ +package com.booleanuk.api.cinema.repository; + +import com.booleanuk.api.cinema.models.Ticket; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface TicketRepository extends JpaRepository { + public List findAllByCustomerIdAndScreeningId(int customerId, int screeningId); + +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/CustomerListResponse.java b/src/main/java/com/booleanuk/api/cinema/response/CustomerListResponse.java new file mode 100644 index 00000000..d4771cd8 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/CustomerListResponse.java @@ -0,0 +1,8 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.models.Customer; + +import java.util.List; + +public class CustomerListResponse extends Response>{ +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/CustomerResponse.java b/src/main/java/com/booleanuk/api/cinema/response/CustomerResponse.java new file mode 100644 index 00000000..ccf0c689 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/CustomerResponse.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.models.Customer; + +public class CustomerResponse extends Response{ + +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/ErrorResponse.java b/src/main/java/com/booleanuk/api/cinema/response/ErrorResponse.java new file mode 100644 index 00000000..ea9855c3 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/ErrorResponse.java @@ -0,0 +1,16 @@ +package com.booleanuk.api.cinema.response; + +import java.util.HashMap; +import java.util.Map; + +public class ErrorResponse extends Response>{ + + public void set(String message){ + this.status = "error"; + Map reply = new HashMap<>(); + reply.put("message", message); + this.data = reply; + } + + +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/MovieDtoResponse.java b/src/main/java/com/booleanuk/api/cinema/response/MovieDtoResponse.java new file mode 100644 index 00000000..50db8118 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/MovieDtoResponse.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.dto.MovieDto; + +public class MovieDtoResponse extends Response{ + +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/MovieListResponse.java b/src/main/java/com/booleanuk/api/cinema/response/MovieListResponse.java new file mode 100644 index 00000000..7b8c888e --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/MovieListResponse.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.models.Movie; +import java.util.List; + +public class MovieListResponse extends Response>{ +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/MovieResponse.java b/src/main/java/com/booleanuk/api/cinema/response/MovieResponse.java new file mode 100644 index 00000000..ff87bc5e --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/MovieResponse.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.dto.MovieDto; +import com.booleanuk.api.cinema.models.Movie; + +public class MovieResponse extends Response{ +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/Response.java b/src/main/java/com/booleanuk/api/cinema/response/Response.java new file mode 100644 index 00000000..f90636c3 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/Response.java @@ -0,0 +1,20 @@ +package com.booleanuk.api.cinema.response; + +public class Response { + protected String status; + protected T data; + + public void set(T data){ + this.status = "success"; + this.data = data; + + } + + public String getStatus() { + return status; + } + + public T getData() { + return data; + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/ScreeningDtoResponse.java b/src/main/java/com/booleanuk/api/cinema/response/ScreeningDtoResponse.java new file mode 100644 index 00000000..2112186e --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/ScreeningDtoResponse.java @@ -0,0 +1,6 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.dto.ScreeningDto; + +public class ScreeningDtoResponse extends Response{ +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/ScreeningListResponse.java b/src/main/java/com/booleanuk/api/cinema/response/ScreeningListResponse.java new file mode 100644 index 00000000..3df04396 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/ScreeningListResponse.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.models.Screening; +import java.util.List; + +public class ScreeningListResponse extends Response>{ +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/ScreeningResponse.java b/src/main/java/com/booleanuk/api/cinema/response/ScreeningResponse.java new file mode 100644 index 00000000..d40fbafa --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/ScreeningResponse.java @@ -0,0 +1,6 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.models.Screening; + +public class ScreeningResponse extends Response{ +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/TicketDtoResponse.java b/src/main/java/com/booleanuk/api/cinema/response/TicketDtoResponse.java new file mode 100644 index 00000000..5307a7c0 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/TicketDtoResponse.java @@ -0,0 +1,6 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.dto.TicketDto; + +public class TicketDtoResponse extends Response{ +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/TicketListResponse.java b/src/main/java/com/booleanuk/api/cinema/response/TicketListResponse.java new file mode 100644 index 00000000..7f8b58c4 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/TicketListResponse.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.models.Ticket; +import java.util.List; + +public class TicketListResponse extends Response>{ +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/TicketResponse.java b/src/main/java/com/booleanuk/api/cinema/response/TicketResponse.java new file mode 100644 index 00000000..9c222ac3 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/TicketResponse.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.dto.TicketDto; +import com.booleanuk.api.cinema.models.Ticket; + +public class TicketResponse extends Response{ +} diff --git a/src/main/resources/application.yml.example b/src/main/resources/application.yml.example deleted file mode 100644 index 275ec30f..00000000 --- a/src/main/resources/application.yml.example +++ /dev/null @@ -1,23 +0,0 @@ -server: - port: 4000 - error: - include-message: always - include-binding-errors: always - include-stacktrace: never - include-exception: false - -spring: - datasource: - url: jdbc:postgresql://DATABASE_URL:5432/DATABASE_NAME - username: DATABASE_USERNAME - password: DATABASE_PASSWORD - max-active: 3 - max-idle: 3 - jpa: - hibernate: - ddl-auto: update - properties: - hibernate: - dialect: org.hibernate.dialect.PostgreSQLDialect - format_sql: true - show-sql: true