From 60ead05cd3b5c2e1d84cf4a89c4e78b1883e0227 Mon Sep 17 00:00:00 2001 From: Thomas Kristiansen Date: Tue, 28 Jan 2025 10:49:59 +0100 Subject: [PATCH 1/3] core done --- .gitignore | 2 + build.gradle | 12 ++++- .../java/com/booleanuk/api/cinema/Main.java | 11 ++++ .../api/cinema/customer/Customer.java | 35 +++++++++++++ .../cinema/customer/CustomerController.java | 49 ++++++++++++++++++ .../cinema/customer/CustomerRepository.java | 6 +++ .../com/booleanuk/api/cinema/movie/Movie.java | 50 +++++++++++++++++++ .../api/cinema/movie/MovieController.java | 49 ++++++++++++++++++ .../api/cinema/movie/MovieRepository.java | 6 +++ .../api/cinema/screening/Screening.java | 44 ++++++++++++++++ .../cinema/screening/ScreeningController.java | 44 ++++++++++++++++ .../cinema/screening/ScreeningRepository.java | 6 +++ 12 files changed, 312 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/booleanuk/api/cinema/Main.java create mode 100644 src/main/java/com/booleanuk/api/cinema/customer/Customer.java create mode 100644 src/main/java/com/booleanuk/api/cinema/customer/CustomerController.java create mode 100644 src/main/java/com/booleanuk/api/cinema/customer/CustomerRepository.java create mode 100644 src/main/java/com/booleanuk/api/cinema/movie/Movie.java create mode 100644 src/main/java/com/booleanuk/api/cinema/movie/MovieController.java create mode 100644 src/main/java/com/booleanuk/api/cinema/movie/MovieRepository.java create mode 100644 src/main/java/com/booleanuk/api/cinema/screening/Screening.java create mode 100644 src/main/java/com/booleanuk/api/cinema/screening/ScreeningController.java create mode 100644 src/main/java/com/booleanuk/api/cinema/screening/ScreeningRepository.java diff --git a/.gitignore b/.gitignore index dc01f204..b8ae3cb6 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,5 @@ out/ ### VS Code ### .vscode/ + +application.yml \ No newline at end of file diff --git a/build.gradle b/build.gradle index 3d7f7607..4e90ab7d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ plugins { id 'java' - id 'org.springframework.boot' version '3.3.1' - id 'io.spring.dependency-management' version '1.1.5' + id 'org.springframework.boot' version '3.4.1' + id 'io.spring.dependency-management' version '1.1.7' } group = 'com.booleanuk' @@ -13,6 +13,12 @@ java { } } +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + repositories { mavenCentral() } @@ -20,8 +26,10 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'org.postgresql:postgresql' + annotationProcessor 'org.projectlombok:lombok' 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/customer/Customer.java b/src/main/java/com/booleanuk/api/cinema/customer/Customer.java new file mode 100644 index 00000000..b4d7ae05 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/customer/Customer.java @@ -0,0 +1,35 @@ +package com.booleanuk.api.cinema.customer; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "customers") +public class Customer { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @Column + private String name; + + @Column + private String email; + + @Column + private String phone; + + @Column + private String created_at; + + @Column + private String updated_at; +} diff --git a/src/main/java/com/booleanuk/api/cinema/customer/CustomerController.java b/src/main/java/com/booleanuk/api/cinema/customer/CustomerController.java new file mode 100644 index 00000000..6c1a446b --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/customer/CustomerController.java @@ -0,0 +1,49 @@ +package com.booleanuk.api.cinema.customer; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +import java.time.LocalDateTime; +import java.util.List; + +@RestController +@RequestMapping("customers") +public class CustomerController { + + @Autowired + private CustomerRepository customerRepository; + + @PostMapping + public ResponseEntity createCustomer(@RequestBody Customer customer) { + customer.setCreated_at(String.valueOf(LocalDateTime.now())); + return new ResponseEntity<>(this.customerRepository.save(customer), HttpStatus.CREATED); + } + + @GetMapping + @ResponseStatus(HttpStatus.OK) + public List getAllCustomers() { + return this.customerRepository.findAll(); + } + + @PutMapping("/{id}") + public ResponseEntity updateCustomer(@PathVariable int id, @RequestBody Customer customer) { + Customer updatedCustomer = this.customerRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,"No customer with that id")); + + updatedCustomer.setName(customer.getName()); + updatedCustomer.setEmail(customer.getEmail()); + updatedCustomer.setPhone(customer.getPhone()); + updatedCustomer.setUpdated_at(String.valueOf(LocalDateTime.now())); + + return new ResponseEntity<>(this.customerRepository.save(updatedCustomer),HttpStatus.CREATED); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteCustomer(@PathVariable int id) { + Customer deletedCustomer = this.customerRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No customer with that id")); + this.customerRepository.delete(deletedCustomer); + return ResponseEntity.ok(deletedCustomer); + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/customer/CustomerRepository.java b/src/main/java/com/booleanuk/api/cinema/customer/CustomerRepository.java new file mode 100644 index 00000000..5c4b6445 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/customer/CustomerRepository.java @@ -0,0 +1,6 @@ +package com.booleanuk.api.cinema.customer; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CustomerRepository extends JpaRepository { +} diff --git a/src/main/java/com/booleanuk/api/cinema/movie/Movie.java b/src/main/java/com/booleanuk/api/cinema/movie/Movie.java new file mode 100644 index 00000000..b067e753 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/movie/Movie.java @@ -0,0 +1,50 @@ +package com.booleanuk.api.cinema.movie; + +import com.booleanuk.api.cinema.screening.Screening; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "movies") +public class Movie { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @Column + private String title; + + @Column + private String rating; + + @Column + private String description; + + @Column + private int runtimeMins; + + @Column + private String created_at; + + @Column + private String updated_at; + + @OneToMany(mappedBy = "movie") + @JsonIgnoreProperties({"movie","id"}) + private List screenings; + + public Movie(int id) { + this.id = id; + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/movie/MovieController.java b/src/main/java/com/booleanuk/api/cinema/movie/MovieController.java new file mode 100644 index 00000000..ba5ebfdc --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/movie/MovieController.java @@ -0,0 +1,49 @@ +package com.booleanuk.api.cinema.movie; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +import java.time.LocalDateTime; +import java.util.List; + +@RestController +@RequestMapping("movies") +public class MovieController { + @Autowired + private MovieRepository movieRepository; + + @PostMapping + public ResponseEntity createMovie(@RequestBody Movie movie) { + movie.setCreated_at(String.valueOf(LocalDateTime.now())); + return new ResponseEntity<>(this.movieRepository.save(movie), HttpStatus.CREATED); + } + + @GetMapping + @ResponseStatus(HttpStatus.OK) + public List getAllMovies() { + return this.movieRepository.findAll(); + } + + @PutMapping("/{id}") + public ResponseEntity updateMovie(@PathVariable int id, @RequestBody Movie movie) { + Movie updatedMovie = this.movieRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No movie with that id")); + + updatedMovie.setTitle(movie.getTitle()); + updatedMovie.setRating(movie.getRating()); + updatedMovie.setDescription(movie.getDescription()); + updatedMovie.setRuntimeMins(movie.getRuntimeMins()); + updatedMovie.setUpdated_at(String.valueOf(LocalDateTime.now())); + + return new ResponseEntity<>(this.movieRepository.save(updatedMovie),HttpStatus.CREATED); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteMovie(@PathVariable int id) { + Movie deletedMovie = this.movieRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No movie with that id")); + this.movieRepository.delete(deletedMovie); + return ResponseEntity.ok(deletedMovie); + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/movie/MovieRepository.java b/src/main/java/com/booleanuk/api/cinema/movie/MovieRepository.java new file mode 100644 index 00000000..67a536f9 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/movie/MovieRepository.java @@ -0,0 +1,6 @@ +package com.booleanuk.api.cinema.movie; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MovieRepository extends JpaRepository { +} diff --git a/src/main/java/com/booleanuk/api/cinema/screening/Screening.java b/src/main/java/com/booleanuk/api/cinema/screening/Screening.java new file mode 100644 index 00000000..9380f433 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/screening/Screening.java @@ -0,0 +1,44 @@ +package com.booleanuk.api.cinema.screening; + +import com.booleanuk.api.cinema.movie.Movie; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonIncludeProperties; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "screenings") +public class Screening { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @Column + private int screenNumber; + + @Column + private int capacity; + + @Column + private String startsAt; + + @Column + private String created_at; + + @Column + private String updated_at; + + @ManyToOne + @JoinColumn(name = "movie_id") + @JsonIgnore + private Movie movie; +} diff --git a/src/main/java/com/booleanuk/api/cinema/screening/ScreeningController.java b/src/main/java/com/booleanuk/api/cinema/screening/ScreeningController.java new file mode 100644 index 00000000..13fb151f --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/screening/ScreeningController.java @@ -0,0 +1,44 @@ +package com.booleanuk.api.cinema.screening; + +import com.booleanuk.api.cinema.movie.Movie; +import com.booleanuk.api.cinema.movie.MovieRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +import java.time.LocalDateTime; +import java.util.List; + +@RestController +public class ScreeningController { + + @Autowired + private ScreeningRepository screeningRepository; + + @Autowired + private MovieRepository movieRepository; + + @PostMapping("movies/{id}/screenings") + public ResponseEntity createScreening(@RequestBody Screening screening, @PathVariable int id) { + Movie movie = this.movieRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No movie with that id")); + screening.setMovie(movie); + screening.setCreated_at(String.valueOf(LocalDateTime.now())); + return new ResponseEntity<>(this.screeningRepository.save(screening), HttpStatus.CREATED); + } + + @GetMapping("movies/{id}/screenings") + @ResponseStatus(HttpStatus.OK) + public List getAllScreenings(@PathVariable int id) { + Movie movie = this.movieRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,"No movie with that id")); + return movie.getScreenings(); + } + + @DeleteMapping("screenings/{id}") + public ResponseEntity deleteScreening(@PathVariable int id) { + Screening deletedScreening = this.screeningRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,"No screening with that id")); + this.screeningRepository.delete(deletedScreening); + return ResponseEntity.ok(deletedScreening); + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/screening/ScreeningRepository.java b/src/main/java/com/booleanuk/api/cinema/screening/ScreeningRepository.java new file mode 100644 index 00000000..33e5ba14 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/screening/ScreeningRepository.java @@ -0,0 +1,6 @@ +package com.booleanuk.api.cinema.screening; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ScreeningRepository extends JpaRepository { +} From 309e8dd36fa3ed7312d2c0bf3d41493d3dc078d6 Mon Sep 17 00:00:00 2001 From: Thomas Kristiansen Date: Tue, 28 Jan 2025 15:50:03 +0100 Subject: [PATCH 2/3] Extensions complete --- .../api/cinema/customer/Customer.java | 9 ++ .../cinema/customer/CustomerController.java | 60 +++++++++--- .../com/booleanuk/api/cinema/movie/Movie.java | 5 +- .../api/cinema/movie/MovieController.java | 63 ++++++++++-- .../api/cinema/response/CustomerResponse.java | 8 ++ .../cinema/response/CustomerResponseList.java | 8 ++ .../api/cinema/response/ErrorResponse.java | 19 ++++ .../api/cinema/response/MovieResponse.java | 6 ++ .../cinema/response/MovieResponseList.java | 8 ++ .../api/cinema/response/Response.java | 15 +++ .../cinema/response/ScreeningResponse.java | 6 ++ .../response/ScreeningResponseList.java | 8 ++ .../api/cinema/response/TicketResponse.java | 6 ++ .../cinema/response/TicketResponseList.java | 8 ++ .../api/cinema/screening/Screening.java | 7 ++ .../cinema/screening/ScreeningController.java | 53 ++++++++-- .../booleanuk/api/cinema/ticket/Ticket.java | 42 ++++++++ .../api/cinema/ticket/TicketController.java | 96 +++++++++++++++++++ .../api/cinema/ticket/TicketRepository.java | 6 ++ 19 files changed, 401 insertions(+), 32 deletions(-) create mode 100644 src/main/java/com/booleanuk/api/cinema/response/CustomerResponse.java create mode 100644 src/main/java/com/booleanuk/api/cinema/response/CustomerResponseList.java create mode 100644 src/main/java/com/booleanuk/api/cinema/response/ErrorResponse.java create mode 100644 src/main/java/com/booleanuk/api/cinema/response/MovieResponse.java create mode 100644 src/main/java/com/booleanuk/api/cinema/response/MovieResponseList.java create mode 100644 src/main/java/com/booleanuk/api/cinema/response/Response.java create mode 100644 src/main/java/com/booleanuk/api/cinema/response/ScreeningResponse.java create mode 100644 src/main/java/com/booleanuk/api/cinema/response/ScreeningResponseList.java create mode 100644 src/main/java/com/booleanuk/api/cinema/response/TicketResponse.java create mode 100644 src/main/java/com/booleanuk/api/cinema/response/TicketResponseList.java create mode 100644 src/main/java/com/booleanuk/api/cinema/ticket/Ticket.java create mode 100644 src/main/java/com/booleanuk/api/cinema/ticket/TicketController.java create mode 100644 src/main/java/com/booleanuk/api/cinema/ticket/TicketRepository.java diff --git a/src/main/java/com/booleanuk/api/cinema/customer/Customer.java b/src/main/java/com/booleanuk/api/cinema/customer/Customer.java index b4d7ae05..e8647610 100644 --- a/src/main/java/com/booleanuk/api/cinema/customer/Customer.java +++ b/src/main/java/com/booleanuk/api/cinema/customer/Customer.java @@ -1,11 +1,16 @@ package com.booleanuk.api.cinema.customer; +import com.booleanuk.api.cinema.ticket.Ticket; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import java.util.List; + @Getter @Setter @NoArgsConstructor @@ -32,4 +37,8 @@ public class Customer { @Column private String updated_at; + + @OneToMany(mappedBy = "customer", cascade = CascadeType.REMOVE) + @JsonIgnore + private List tickets; } diff --git a/src/main/java/com/booleanuk/api/cinema/customer/CustomerController.java b/src/main/java/com/booleanuk/api/cinema/customer/CustomerController.java index 6c1a446b..ab075fbd 100644 --- a/src/main/java/com/booleanuk/api/cinema/customer/CustomerController.java +++ b/src/main/java/com/booleanuk/api/cinema/customer/CustomerController.java @@ -1,5 +1,9 @@ package com.booleanuk.api.cinema.customer; +import com.booleanuk.api.cinema.response.CustomerResponse; +import com.booleanuk.api.cinema.response.CustomerResponseList; +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; @@ -17,33 +21,67 @@ public class CustomerController { private CustomerRepository customerRepository; @PostMapping - public ResponseEntity createCustomer(@RequestBody Customer customer) { - customer.setCreated_at(String.valueOf(LocalDateTime.now())); - return new ResponseEntity<>(this.customerRepository.save(customer), HttpStatus.CREATED); + public ResponseEntity> createCustomer(@RequestBody Customer customer) { + CustomerResponse response = new CustomerResponse(); + try { + customer.setCreated_at(String.valueOf(LocalDateTime.now())); + response.set(this.customerRepository.save(customer)); + } catch (Exception e) { + ErrorResponse error = new ErrorResponse(); + error.set("bad request"); + return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + } + return new ResponseEntity<>(response, HttpStatus.CREATED); } @GetMapping @ResponseStatus(HttpStatus.OK) - public List getAllCustomers() { - return this.customerRepository.findAll(); + public ResponseEntity getAllCustomers() { + CustomerResponseList response = new CustomerResponseList(); + response.set(this.customerRepository.findAll()); + return ResponseEntity.ok(response); } @PutMapping("/{id}") - public ResponseEntity updateCustomer(@PathVariable int id, @RequestBody Customer customer) { - Customer updatedCustomer = this.customerRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,"No customer with that id")); + public ResponseEntity> updateCustomer(@PathVariable int id, @RequestBody Customer customer) { + Customer updatedCustomer = null; + CustomerResponse response = new CustomerResponse(); + try { + updatedCustomer = this.customerRepository.findById(id).orElse(null); + } catch (Exception e) { + ErrorResponse error = new ErrorResponse(); + error.set("bad request"); + return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + } + + if (updatedCustomer == null) { + ErrorResponse error = new ErrorResponse(); + error.set("not found"); + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } updatedCustomer.setName(customer.getName()); updatedCustomer.setEmail(customer.getEmail()); updatedCustomer.setPhone(customer.getPhone()); updatedCustomer.setUpdated_at(String.valueOf(LocalDateTime.now())); + response.set(this.customerRepository.save(updatedCustomer)); - return new ResponseEntity<>(this.customerRepository.save(updatedCustomer),HttpStatus.CREATED); + return new ResponseEntity<>(response,HttpStatus.CREATED); } @DeleteMapping("/{id}") - public ResponseEntity deleteCustomer(@PathVariable int id) { - Customer deletedCustomer = this.customerRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No customer with that id")); + public ResponseEntity> deleteCustomer(@PathVariable int id) { + Customer deletedCustomer = this.customerRepository.findById(id).orElse(null); + CustomerResponse response = new CustomerResponse(); + + if (deletedCustomer == null) { + ErrorResponse error = new ErrorResponse(); + error.set("bad request"); + return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + } + this.customerRepository.delete(deletedCustomer); - return ResponseEntity.ok(deletedCustomer); + response.set(deletedCustomer); + return ResponseEntity.ok(response); } } diff --git a/src/main/java/com/booleanuk/api/cinema/movie/Movie.java b/src/main/java/com/booleanuk/api/cinema/movie/Movie.java index b067e753..b56488b6 100644 --- a/src/main/java/com/booleanuk/api/cinema/movie/Movie.java +++ b/src/main/java/com/booleanuk/api/cinema/movie/Movie.java @@ -1,6 +1,7 @@ package com.booleanuk.api.cinema.movie; import com.booleanuk.api.cinema.screening.Screening; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import jakarta.persistence.*; import lombok.AllArgsConstructor; @@ -40,8 +41,8 @@ public class Movie { @Column private String updated_at; - @OneToMany(mappedBy = "movie") - @JsonIgnoreProperties({"movie","id"}) + @OneToMany(mappedBy = "movie", cascade = CascadeType.REMOVE) + @JsonIgnore private List screenings; public Movie(int id) { diff --git a/src/main/java/com/booleanuk/api/cinema/movie/MovieController.java b/src/main/java/com/booleanuk/api/cinema/movie/MovieController.java index ba5ebfdc..3eac2f19 100644 --- a/src/main/java/com/booleanuk/api/cinema/movie/MovieController.java +++ b/src/main/java/com/booleanuk/api/cinema/movie/MovieController.java @@ -1,5 +1,9 @@ package com.booleanuk.api.cinema.movie; +import com.booleanuk.api.cinema.response.ErrorResponse; +import com.booleanuk.api.cinema.response.MovieResponse; +import com.booleanuk.api.cinema.response.MovieResponseList; +import com.booleanuk.api.cinema.response.Response; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -16,20 +20,48 @@ public class MovieController { private MovieRepository movieRepository; @PostMapping - public ResponseEntity createMovie(@RequestBody Movie movie) { + public ResponseEntity> createMovie(@RequestBody Movie movie) { + MovieResponse response = new MovieResponse(); movie.setCreated_at(String.valueOf(LocalDateTime.now())); - return new ResponseEntity<>(this.movieRepository.save(movie), HttpStatus.CREATED); + + try { + response.set(this.movieRepository.save(movie)); + } catch (Exception e) { + ErrorResponse error = new ErrorResponse(); + error.set("bad request"); + return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + } + + return new ResponseEntity<>(response,HttpStatus.CREATED); } @GetMapping @ResponseStatus(HttpStatus.OK) - public List getAllMovies() { - return this.movieRepository.findAll(); + public ResponseEntity getAllMovies() { + MovieResponseList response = new MovieResponseList(); + response.set(this.movieRepository.findAll()); + return ResponseEntity.ok(response); } @PutMapping("/{id}") - public ResponseEntity updateMovie(@PathVariable int id, @RequestBody Movie movie) { - Movie updatedMovie = this.movieRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No movie with that id")); + public ResponseEntity> updateMovie(@PathVariable int id, @RequestBody Movie movie) { + Movie updatedMovie = null; + MovieResponse response = new MovieResponse(); + + + try { + updatedMovie = this.movieRepository.findById(id).orElse(null); + } catch (Exception e) { + ErrorResponse error = new ErrorResponse(); + error.set("bad request"); + return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + } + + if (updatedMovie == null) { + ErrorResponse error = new ErrorResponse(); + error.set("not found"); + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } updatedMovie.setTitle(movie.getTitle()); updatedMovie.setRating(movie.getRating()); @@ -37,13 +69,24 @@ public ResponseEntity updateMovie(@PathVariable int id, @RequestBody Movi updatedMovie.setRuntimeMins(movie.getRuntimeMins()); updatedMovie.setUpdated_at(String.valueOf(LocalDateTime.now())); - return new ResponseEntity<>(this.movieRepository.save(updatedMovie),HttpStatus.CREATED); + response.set(this.movieRepository.save(updatedMovie)); + + return new ResponseEntity<>(response, HttpStatus.CREATED); } @DeleteMapping("/{id}") - public ResponseEntity deleteMovie(@PathVariable int id) { - Movie deletedMovie = this.movieRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No movie with that id")); + public ResponseEntity> deleteMovie(@PathVariable int id) { + Movie deletedMovie = this.movieRepository.findById(id).orElse(null); + MovieResponse response = new MovieResponse(); + + if(deletedMovie == null) { + ErrorResponse error = new ErrorResponse(); + error.set("bad request"); + return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + } + this.movieRepository.delete(deletedMovie); - return ResponseEntity.ok(deletedMovie); + response.set(deletedMovie); + return ResponseEntity.ok(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..8354406d --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/CustomerResponse.java @@ -0,0 +1,8 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.customer.Customer; + +import java.util.List; + +public class CustomerResponse extends Response { +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/CustomerResponseList.java b/src/main/java/com/booleanuk/api/cinema/response/CustomerResponseList.java new file mode 100644 index 00000000..c3c0574d --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/CustomerResponseList.java @@ -0,0 +1,8 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.customer.Customer; + +import java.util.List; + +public class CustomerResponseList 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..85935651 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/ErrorResponse.java @@ -0,0 +1,19 @@ +package com.booleanuk.api.cinema.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.HashMap; +import java.util.Map; + +@Getter +@NoArgsConstructor +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/MovieResponse.java b/src/main/java/com/booleanuk/api/cinema/response/MovieResponse.java new file mode 100644 index 00000000..cfcb1748 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/MovieResponse.java @@ -0,0 +1,6 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.movie.Movie; + +public class MovieResponse extends Response { +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/MovieResponseList.java b/src/main/java/com/booleanuk/api/cinema/response/MovieResponseList.java new file mode 100644 index 00000000..7ef72726 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/MovieResponseList.java @@ -0,0 +1,8 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.movie.Movie; + +import java.util.List; + +public class MovieResponseList 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..51a007ec --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/Response.java @@ -0,0 +1,15 @@ +package com.booleanuk.api.cinema.response; + +import lombok.Getter; + +@Getter +public class Response { + protected String status; + protected T data; + + public void set(T data) { + this.status = "success"; + this.data = data; + } + +} 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..e711bc0b --- /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.screening.Screening; + +public class ScreeningResponse extends Response { +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/ScreeningResponseList.java b/src/main/java/com/booleanuk/api/cinema/response/ScreeningResponseList.java new file mode 100644 index 00000000..86f1b739 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/ScreeningResponseList.java @@ -0,0 +1,8 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.screening.Screening; + +import java.util.List; + +public class ScreeningResponseList 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..841c7a85 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/TicketResponse.java @@ -0,0 +1,6 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.ticket.Ticket; + +public class TicketResponse extends Response { +} diff --git a/src/main/java/com/booleanuk/api/cinema/response/TicketResponseList.java b/src/main/java/com/booleanuk/api/cinema/response/TicketResponseList.java new file mode 100644 index 00000000..1083b034 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/response/TicketResponseList.java @@ -0,0 +1,8 @@ +package com.booleanuk.api.cinema.response; + +import com.booleanuk.api.cinema.ticket.Ticket; + +import java.util.List; + +public class TicketResponseList extends Response> { +} diff --git a/src/main/java/com/booleanuk/api/cinema/screening/Screening.java b/src/main/java/com/booleanuk/api/cinema/screening/Screening.java index 9380f433..14e8066c 100644 --- a/src/main/java/com/booleanuk/api/cinema/screening/Screening.java +++ b/src/main/java/com/booleanuk/api/cinema/screening/Screening.java @@ -1,6 +1,7 @@ package com.booleanuk.api.cinema.screening; import com.booleanuk.api.cinema.movie.Movie; +import com.booleanuk.api.cinema.ticket.Ticket; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIncludeProperties; @@ -10,6 +11,8 @@ import lombok.NoArgsConstructor; import lombok.Setter; +import java.util.List; + @Getter @Setter @NoArgsConstructor @@ -41,4 +44,8 @@ public class Screening { @JoinColumn(name = "movie_id") @JsonIgnore private Movie movie; + + @OneToMany(mappedBy = "screening", cascade = CascadeType.REMOVE) + @JsonIgnore + private List tickets; } diff --git a/src/main/java/com/booleanuk/api/cinema/screening/ScreeningController.java b/src/main/java/com/booleanuk/api/cinema/screening/ScreeningController.java index 13fb151f..572002cb 100644 --- a/src/main/java/com/booleanuk/api/cinema/screening/ScreeningController.java +++ b/src/main/java/com/booleanuk/api/cinema/screening/ScreeningController.java @@ -2,6 +2,10 @@ import com.booleanuk.api.cinema.movie.Movie; import com.booleanuk.api.cinema.movie.MovieRepository; +import com.booleanuk.api.cinema.response.ErrorResponse; +import com.booleanuk.api.cinema.response.Response; +import com.booleanuk.api.cinema.response.ScreeningResponse; +import com.booleanuk.api.cinema.response.ScreeningResponseList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -21,24 +25,55 @@ public class ScreeningController { private MovieRepository movieRepository; @PostMapping("movies/{id}/screenings") - public ResponseEntity createScreening(@RequestBody Screening screening, @PathVariable int id) { - Movie movie = this.movieRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No movie with that id")); - screening.setMovie(movie); - screening.setCreated_at(String.valueOf(LocalDateTime.now())); - return new ResponseEntity<>(this.screeningRepository.save(screening), HttpStatus.CREATED); + public ResponseEntity> createScreening(@RequestBody Screening screening, @PathVariable int id) { + Movie movie = this.movieRepository.findById(id).orElse(null); + ScreeningResponse response = new ScreeningResponse(); + + if (movie == null) { + ErrorResponse error = new ErrorResponse(); + error.set("Not found"); + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } + + try { + screening.setMovie(movie); + screening.setCreated_at(String.valueOf(LocalDateTime.now())); + response.set(this.screeningRepository.save(screening)); + } catch (Exception e) { + ErrorResponse error = new ErrorResponse(); + error.set("Bad request"); + return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + } + return new ResponseEntity<>(response, HttpStatus.CREATED); } @GetMapping("movies/{id}/screenings") @ResponseStatus(HttpStatus.OK) - public List getAllScreenings(@PathVariable int id) { + public ResponseEntity> getAllScreenings(@PathVariable int id) { Movie movie = this.movieRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,"No movie with that id")); - return movie.getScreenings(); + ScreeningResponseList response = new ScreeningResponseList(); + + if (movie == null) { + ErrorResponse error = new ErrorResponse(); + error.set("Not found"); + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } + response.set(movie.getScreenings()); + return ResponseEntity.ok(response); } @DeleteMapping("screenings/{id}") - public ResponseEntity deleteScreening(@PathVariable int id) { + public ResponseEntity> deleteScreening(@PathVariable int id) { Screening deletedScreening = this.screeningRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,"No screening with that id")); + ScreeningResponse response = new ScreeningResponse(); + + if (deletedScreening == null) { + ErrorResponse error = new ErrorResponse(); + error.set("Not found"); + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } this.screeningRepository.delete(deletedScreening); - return ResponseEntity.ok(deletedScreening); + response.set(deletedScreening); + return ResponseEntity.ok(response); } } diff --git a/src/main/java/com/booleanuk/api/cinema/ticket/Ticket.java b/src/main/java/com/booleanuk/api/cinema/ticket/Ticket.java new file mode 100644 index 00000000..362228fb --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/ticket/Ticket.java @@ -0,0 +1,42 @@ +package com.booleanuk.api.cinema.ticket; + +import com.booleanuk.api.cinema.customer.Customer; +import com.booleanuk.api.cinema.screening.Screening; +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "tickets") +public class Ticket { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @Column + private int numSeats; + + @Column + private String created_at; + + @Column + private String update_at; + + @ManyToOne + @JoinColumn(name = "customer_id") + @JsonIgnore + private Customer customer; + + @ManyToOne + @JoinColumn(name = "screening_id") + @JsonIgnore + private Screening screening; +} diff --git a/src/main/java/com/booleanuk/api/cinema/ticket/TicketController.java b/src/main/java/com/booleanuk/api/cinema/ticket/TicketController.java new file mode 100644 index 00000000..72a455fa --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/ticket/TicketController.java @@ -0,0 +1,96 @@ +package com.booleanuk.api.cinema.ticket; + +import com.booleanuk.api.cinema.customer.Customer; +import com.booleanuk.api.cinema.customer.CustomerRepository; +import com.booleanuk.api.cinema.movie.Movie; +import com.booleanuk.api.cinema.response.ErrorResponse; +import com.booleanuk.api.cinema.response.Response; +import com.booleanuk.api.cinema.response.TicketResponse; +import com.booleanuk.api.cinema.response.TicketResponseList; +import com.booleanuk.api.cinema.screening.Screening; +import com.booleanuk.api.cinema.screening.ScreeningRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@RestController +public class TicketController { + + @Autowired + private TicketRepository ticketRepository; + + @Autowired + private CustomerRepository customerRepository; + + @Autowired + private ScreeningRepository screeningRepository; + + @PostMapping("customers/{customerId}/screenings/{screeningId}") + public ResponseEntity> bookTicket(@PathVariable int customerId, @PathVariable int screeningId, @RequestBody Ticket ticket) { + Customer customer = this.customerRepository.findById(customerId).orElse(null); + Screening screening = this.screeningRepository.findById(screeningId).orElse(null); + TicketResponse response = new TicketResponse(); + + if (customer == null || screening == null) { + ErrorResponse error = new ErrorResponse(); + error.set("Not found"); + return new ResponseEntity<>(error,HttpStatus.NOT_FOUND); + } + + try { + ticket.setCustomer(customer); + ticket.setScreening(screening); + ticket.setCreated_at(String.valueOf(LocalDateTime.now())); + response.set(this.ticketRepository.save(ticket)); + } catch (Exception e) { + ErrorResponse error = new ErrorResponse(); + error.set("Bad request"); + return new ResponseEntity<>(error,HttpStatus.BAD_REQUEST); + } + return new ResponseEntity<>(response, HttpStatus.CREATED); + } + + @GetMapping("customers/{customerId}/screenings/{screeningId}") + @ResponseStatus(HttpStatus.OK) + public ResponseEntity> getAllTickets(@PathVariable int customerId, @PathVariable int screeningId) { + Customer customer = this.customerRepository.findById(customerId).orElse(null); + TicketResponseList response = new TicketResponseList(); + List output = new ArrayList<>(); + + for(Ticket ticket : customer.getTickets()) { + if(ticket.getScreening().getId() == screeningId) { + output.add(ticket); + } + } + + response.set(output); + + if(output.isEmpty()) { + ErrorResponse error = new ErrorResponse(); + error.set("Not found"); + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); + } + return ResponseEntity.ok(response); + } + + @DeleteMapping("tickets/{id}") + public ResponseEntity> deleteTicket(@PathVariable int id) { + Ticket deletedTicket = this.ticketRepository.findById(id).orElse(null); + TicketResponse response = new TicketResponse(); + + if (deletedTicket == null) { + ErrorResponse error = new ErrorResponse(); + error.set("Not found"); + return new ResponseEntity<>(error,HttpStatus.NOT_FOUND); + } + this.ticketRepository.delete(deletedTicket); + response.set(deletedTicket); + return ResponseEntity.ok(response); + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/ticket/TicketRepository.java b/src/main/java/com/booleanuk/api/cinema/ticket/TicketRepository.java new file mode 100644 index 00000000..41f00e55 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/ticket/TicketRepository.java @@ -0,0 +1,6 @@ +package com.booleanuk.api.cinema.ticket; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TicketRepository extends JpaRepository { +} From 22486a67798867b3b427017bd99690ed4d3a42b0 Mon Sep 17 00:00:00 2001 From: Thomas Kristiansen Date: Tue, 28 Jan 2025 15:56:25 +0100 Subject: [PATCH 3/3] fixed misspelling --- .../com/booleanuk/api/cinema/customer/CustomerController.java | 4 ++-- .../java/com/booleanuk/api/cinema/movie/MovieController.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/booleanuk/api/cinema/customer/CustomerController.java b/src/main/java/com/booleanuk/api/cinema/customer/CustomerController.java index ab075fbd..7366b9be 100644 --- a/src/main/java/com/booleanuk/api/cinema/customer/CustomerController.java +++ b/src/main/java/com/booleanuk/api/cinema/customer/CustomerController.java @@ -76,8 +76,8 @@ public ResponseEntity> deleteCustomer(@PathVariable int id) { if (deletedCustomer == null) { ErrorResponse error = new ErrorResponse(); - error.set("bad request"); - return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + error.set("Not found"); + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); } this.customerRepository.delete(deletedCustomer); diff --git a/src/main/java/com/booleanuk/api/cinema/movie/MovieController.java b/src/main/java/com/booleanuk/api/cinema/movie/MovieController.java index 3eac2f19..754f710f 100644 --- a/src/main/java/com/booleanuk/api/cinema/movie/MovieController.java +++ b/src/main/java/com/booleanuk/api/cinema/movie/MovieController.java @@ -81,8 +81,8 @@ public ResponseEntity> deleteMovie(@PathVariable int id) { if(deletedMovie == null) { ErrorResponse error = new ErrorResponse(); - error.set("bad request"); - return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + error.set("Not found"); + return new ResponseEntity<>(error, HttpStatus.NOT_FOUND); } this.movieRepository.delete(deletedMovie);