diff --git a/build.gradle b/build.gradle index 3d7f7607..1c6ff408 100644 --- a/build.gradle +++ b/build.gradle @@ -24,6 +24,7 @@ dependencies { runtimeOnly 'org.postgresql:postgresql' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + implementation 'org.springframework.boot:spring-boot-starter-validation' } tasks.named('test') { diff --git a/src/main/java/com/booleanuk/api/Main.java b/src/main/java/com/booleanuk/api/Main.java new file mode 100644 index 00000000..289a5189 --- /dev/null +++ b/src/main/java/com/booleanuk/api/Main.java @@ -0,0 +1,11 @@ +package com.booleanuk.api; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication(scanBasePackages = {"com.booleanuk.api"}) +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.java b/src/main/java/com/booleanuk/api/cinema/Customer.java new file mode 100644 index 00000000..3c242652 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/Customer.java @@ -0,0 +1,128 @@ +package com.booleanuk.api.cinema; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonManagedReference; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotBlank; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + + +@Entity +@Table(name = "customers") +public class Customer { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @NotBlank + @Column + private String name; + @NotBlank + @Column + private String email; + @NotBlank + @Column + private String phone; + @Column(name = "created_at") + private LocalDateTime createdAt; + @Column(name = "updated_at") + private LocalDateTime updatedAt; + + @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, orphanRemoval = true) + @JsonManagedReference(value = "customer-tickets") + @JsonIgnore + private List tickets; + + + + + + + public Customer(String name, String email, String phone) { + this.name = name; + this.email = email; + this.phone = phone; + this.tickets = new ArrayList<>(); + } + + public Customer() { + } + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(); + this.updatedAt = LocalDateTime.now(); + } + + @PreUpdate + protected void onUpdate() { + this.updatedAt = LocalDateTime.now(); + } + + + public Integer getId() { + return id; + } + + public void setId(Integer 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; + } + + + public List getTickets() { + return tickets; + } + + public void setTickets(List tickets) { + this.tickets = tickets; + } + + + + +} + + diff --git a/src/main/java/com/booleanuk/api/cinema/DTO/BadRequestException.java b/src/main/java/com/booleanuk/api/cinema/DTO/BadRequestException.java new file mode 100644 index 00000000..7214697f --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/DTO/BadRequestException.java @@ -0,0 +1,10 @@ +package com.booleanuk.api.cinema.DTO; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +public class BadRequestException extends RuntimeException { + public BadRequestException(String message) { + super(message); + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/DTO/ErrorData.java b/src/main/java/com/booleanuk/api/cinema/DTO/ErrorData.java new file mode 100644 index 00000000..d0d43547 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/DTO/ErrorData.java @@ -0,0 +1,19 @@ +package com.booleanuk.api.cinema.DTO; + + +public class ErrorData { + private String message; + + // Constructor, getters, and setters + public ErrorData(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/DTO/ErrorResponse.java b/src/main/java/com/booleanuk/api/cinema/DTO/ErrorResponse.java new file mode 100644 index 00000000..f4fcea20 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/DTO/ErrorResponse.java @@ -0,0 +1,32 @@ +package com.booleanuk.api.cinema.DTO; + +public class ErrorResponse { + private String status; + private ErrorData data; + + // No-argument constructor + public ErrorResponse() {} + + // Parameterized constructor + public ErrorResponse(String status, ErrorData data) { + this.status = status; + this.data = data; + } + + // Getters and setters + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public ErrorData getData() { + return data; + } + + public void setData(ErrorData data) { + this.data = data; + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/DTO/GlobalExceptionHandler.java b/src/main/java/com/booleanuk/api/cinema/DTO/GlobalExceptionHandler.java new file mode 100644 index 00000000..7cd00ffa --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/DTO/GlobalExceptionHandler.java @@ -0,0 +1,22 @@ +package com.booleanuk.api.cinema.DTO; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(NotFoundException.class) + public ResponseEntity handleNotFoundException(NotFoundException ex) { + ErrorResponse errorResponse = new ErrorResponse("error", new ErrorData(ex.getMessage())); + return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(BadRequestException.class) + public ResponseEntity handleBadRequestException(BadRequestException ex) { + ErrorResponse errorResponse = new ErrorResponse("error", new ErrorData(ex.getMessage())); + return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + } + +} diff --git a/src/main/java/com/booleanuk/api/cinema/DTO/NotFoundException.java b/src/main/java/com/booleanuk/api/cinema/DTO/NotFoundException.java new file mode 100644 index 00000000..4f811318 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/DTO/NotFoundException.java @@ -0,0 +1,10 @@ +package com.booleanuk.api.cinema.DTO; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +public class NotFoundException extends RuntimeException { + public NotFoundException(String message) { + super(message); + } +} 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..f0323299 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/DTO/TicketDTO.java @@ -0,0 +1,82 @@ +package com.booleanuk.api.cinema.DTO; + +import java.time.LocalDateTime; + +public class TicketDTO { + private Integer id; + private int numSeats; + private LocalDateTime startsAt; + private LocalDateTime createdAt; + private LocalDateTime updatedAt; + private Integer customerId; + private Integer screeningId; + + public TicketDTO() { + } + + public TicketDTO(Integer id, int numSeats, LocalDateTime startsAt, LocalDateTime createdAt, LocalDateTime updatedAt, Integer customerId, Integer screeningId) { + this.id = id; + this.numSeats = numSeats; + this.startsAt = startsAt; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + this.customerId = customerId; + this.screeningId = screeningId; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public int getNumSeats() { + return numSeats; + } + + public void setNumSeats(int numSeats) { + this.numSeats = numSeats; + } + + public LocalDateTime getStartsAt() { + return startsAt; + } + + public void setStartsAt(LocalDateTime startsAt) { + this.startsAt = startsAt; + } + + 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 Integer getCustomerId() { + return customerId; + } + + public void setCustomerId(Integer customerId) { + this.customerId = customerId; + } + + public Integer getScreeningId() { + return screeningId; + } + + public void setScreeningId(Integer screeningId) { + this.screeningId = screeningId; + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/Movie.java b/src/main/java/com/booleanuk/api/cinema/Movie.java new file mode 100644 index 00000000..fc1253b4 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/Movie.java @@ -0,0 +1,121 @@ +package com.booleanuk.api.cinema; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonManagedReference; +import jakarta.persistence.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Table(name = "Movies") +public class Movie { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column + private String title; + @Column + private String rating; + @Column + private String description; + @Column + private int runtimeMins; + @Column(name = "created_at") + private LocalDateTime createdAt; + @Column(name = "updated_at") + private LocalDateTime updatedAt; + + @OneToMany(mappedBy = "movie", cascade = CascadeType.ALL, orphanRemoval = true) + @JsonManagedReference(value = "movie-screenings") + @JsonIgnore + private List screenings; + + public Movie(String title, String rating, String description, int runtimeMins) { + this.title = title; + this.rating = rating; + this.description = description; + this.runtimeMins = runtimeMins; + this.screenings = new ArrayList<>(); + } + + public Movie() { + } + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(); + this.updatedAt = LocalDateTime.now(); + } + + @PreUpdate + protected void onUpdate() { + this.updatedAt = LocalDateTime.now(); + } + + public Integer getId() { + return id; + } + + public void setId(Integer 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; + } + + public List getScreenings() { + return screenings; + } + + public void setScreenings(List screenings) { + this.screenings = screenings; + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/Screening.java b/src/main/java/com/booleanuk/api/cinema/Screening.java new file mode 100644 index 00000000..0dc1254a --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/Screening.java @@ -0,0 +1,114 @@ +package com.booleanuk.api.cinema; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonManagedReference; +import jakarta.persistence.*; + +import java.time.LocalDateTime; +import java.util.List; + +@Entity +@Table(name = "Screenings") +public class Screening { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column + private int screenNumber; + @Column + private int capacity; + @ManyToOne + @JoinColumn(name = "movie_id") + @JsonBackReference(value = "movie-screenings") + private Movie movie; + @Column + private LocalDateTime startsAt; + @Column(name = "created_at") + private LocalDateTime createdAt; + @Column(name = "updated_at") + private LocalDateTime updatedAt; + + @OneToMany(mappedBy = "screening", cascade = CascadeType.ALL, orphanRemoval = true) + @JsonManagedReference(value = "screening-ticket") + @JsonIgnore + private List tickets; + + public Screening(int screenNumber, int capacity, LocalDateTime startsAt) { + this.screenNumber = screenNumber; + this.capacity = capacity; + this.startsAt = startsAt; + } + + public Screening() { + } + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(); + this.updatedAt = LocalDateTime.now(); + } + + @PreUpdate + protected void onUpdate() { + this.updatedAt = LocalDateTime.now(); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + 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 getStartsAt() { + return startsAt; + } + + public void setStartsAt(LocalDateTime startsAt) { + this.startsAt = startsAt; + } + + 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; + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/Ticket.java b/src/main/java/com/booleanuk/api/cinema/Ticket.java new file mode 100644 index 00000000..d412210f --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/Ticket.java @@ -0,0 +1,111 @@ +package com.booleanuk.api.cinema; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.*; +import org.springframework.cglib.core.Local; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Entity +@Table(name = "tickets") +public class Ticket { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column + private int numSeats; + @Column + private LocalDateTime startsAt; + @Column(name = "created_at") + private LocalDateTime createdAt; + @Column(name = "updated_at") + private LocalDateTime updatedAt; + + @ManyToOne + @JoinColumn(name = "customer_id") + @JsonBackReference(value = "customer-tickets") + private Customer customer; + + @ManyToOne + @JoinColumn(name = "screening_id") + @JsonBackReference(value = "screening-ticket") + private Screening screening; + + public Ticket(int numSeats) { + this.numSeats = numSeats; + } + + public Ticket() { + } + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(); + this.updatedAt = LocalDateTime.now(); + } + + @PreUpdate + protected void onUpdate() { + this.updatedAt = LocalDateTime.now(); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + 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; + } + + 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 LocalDateTime getStartsAt() { + return startsAt; + } + + public void setStartsAt(LocalDateTime startsAt) { + this.startsAt = startsAt; + } +} + + diff --git a/src/main/java/com/booleanuk/api/cinema/controller/CustomerController.java b/src/main/java/com/booleanuk/api/cinema/controller/CustomerController.java new file mode 100644 index 00000000..f03af6f2 --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/controller/CustomerController.java @@ -0,0 +1,72 @@ + +package com.booleanuk.api.cinema.controller; + +import com.booleanuk.api.cinema.Customer; +import com.booleanuk.api.cinema.DTO.BadRequestException; +import com.booleanuk.api.cinema.DTO.NotFoundException; +//import com.booleanuk.api.cinema.DTO.ErrorResponse; +import com.booleanuk.api.cinema.repository.CustomerRepository; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +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.util.List; + + +@RestController +@RequestMapping("customers") +public class CustomerController { + @Autowired + private final CustomerRepository customerRepository; + + public CustomerController(CustomerRepository customerRepository) { + this.customerRepository = customerRepository; + } + + @GetMapping + public List getAllMovies() { + return this.customerRepository.findAll(); + } + + + + + @PostMapping + public ResponseEntity createCustomer (@Valid @RequestBody Customer customer){ + return new ResponseEntity<>(this.customerRepository.save(customer), HttpStatus.CREATED); + } + + + @PutMapping("{id}") + public ResponseEntity updateCustomer(@PathVariable int id, @Valid @RequestBody Customer customer) { + if(customer.getName() == null || customer.getName().length() < 2) { + throw new BadRequestException("Name must be at least 2 characters long"); + } + + Customer customerToUpdate = this.customerRepository.findById(id).orElseThrow( + () -> new NotFoundException("No customer with that ID found") + ); + // Only update the fields that are being changed + customerToUpdate.setName(customer.getName()); + customerToUpdate.setEmail(customer.getEmail()); + customerToUpdate.setPhone(customer.getPhone()); + + return new ResponseEntity<>(this.customerRepository.save(customerToUpdate), HttpStatus.CREATED); + } + + + @DeleteMapping("{id}") + public ResponseEntity deleteCustomer(@PathVariable int id) { + Customer customerToDelete = this.customerRepository.findById(id).orElseThrow( + () -> new NotFoundException("No customer with that ID found") + ); + this.customerRepository.delete(customerToDelete); + return ResponseEntity.ok(customerToDelete); + } + + +} + diff --git a/src/main/java/com/booleanuk/api/cinema/controller/MovieController.java b/src/main/java/com/booleanuk/api/cinema/controller/MovieController.java new file mode 100644 index 00000000..645c7f2a --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/controller/MovieController.java @@ -0,0 +1,60 @@ +package com.booleanuk.api.cinema.controller; + +import com.booleanuk.api.cinema.DTO.BadRequestException; +import com.booleanuk.api.cinema.DTO.NotFoundException; +import com.booleanuk.api.cinema.Movie; +import com.booleanuk.api.cinema.repository.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 java.util.List; + +@RestController +@RequestMapping("movies") +public class MovieController { + @Autowired + private final MovieRepository movieRepository; + + public MovieController(MovieRepository movieRepository) { + this.movieRepository = movieRepository; + } + + @GetMapping + public List getAllMovies() { + return this.movieRepository.findAll(); + } + + @PostMapping + public ResponseEntity createMovie(@RequestBody Movie movie) { + return new ResponseEntity<>(this.movieRepository.save(movie), HttpStatus.CREATED); + } + + @PutMapping("{id}") + public ResponseEntity updateMovie(@PathVariable int id, @RequestBody Movie movie) { + if(movie.getTitle() == null || movie.getDescription().length() < 2) { + throw new BadRequestException("bad request"); + } + Movie movieToUpdate = this.movieRepository.findById(id).orElseThrow( + () -> new NotFoundException("No movie with that ID found") + ); + movieToUpdate.setDescription(movie.getDescription()); + movieToUpdate.setRating(movie.getRating()); + movieToUpdate.setTitle(movie.getTitle()); + movieToUpdate.setRuntimeMins(movie.getRuntimeMins()); + + movie.setId(movieToUpdate.getId()); + return new ResponseEntity<>(this.movieRepository.save(movieToUpdate), HttpStatus.CREATED); + } + + @DeleteMapping("{id}") + public ResponseEntity deleteMovie(@PathVariable int id) { + Movie movieToDelete = this.movieRepository.findById(id).orElseThrow( + () -> new NotFoundException("No movie with that ID found") + ); + this.movieRepository.delete(movieToDelete); + return ResponseEntity.ok(movieToDelete); + } + +} diff --git a/src/main/java/com/booleanuk/api/cinema/controller/ScreeningController.java b/src/main/java/com/booleanuk/api/cinema/controller/ScreeningController.java new file mode 100644 index 00000000..a4e87fae --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/controller/ScreeningController.java @@ -0,0 +1,73 @@ +package com.booleanuk.api.cinema.controller; + +import com.booleanuk.api.cinema.DTO.BadRequestException; +import com.booleanuk.api.cinema.DTO.NotFoundException; +import com.booleanuk.api.cinema.Movie; +import com.booleanuk.api.cinema.Screening; +import com.booleanuk.api.cinema.repository.MovieRepository; +import com.booleanuk.api.cinema.repository.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 java.util.List; + +@RestController +@RequestMapping("/movies/{movieId}/screenings") +public class ScreeningController { + @Autowired + private final ScreeningRepository screeningRepository; + private final MovieRepository movieRepository; + + public ScreeningController(ScreeningRepository screeningRepository, MovieRepository movieRepository) { + this.screeningRepository = screeningRepository; + this.movieRepository = movieRepository; + } + + @GetMapping + public List getAllScreenings() { + return this.screeningRepository.findAll(); + } + + @PostMapping + public ResponseEntity createScreening(@PathVariable int movieId, @RequestBody Screening screening) { + + + Movie movie = this.movieRepository.findById(movieId).orElseThrow( + () -> new NotFoundException("No movie with that ID found") + ); + screening.setMovie(movie); + return new ResponseEntity<>(this.screeningRepository.save(screening), HttpStatus.CREATED); + } + + @GetMapping("{id}") + public ResponseEntity getScreeningById(@PathVariable int id) { + Screening screening = null; + screening = this.screeningRepository.findById(id).orElseThrow( + () -> new NotFoundException("No screening with that ID found") + ); + return ResponseEntity.ok(screening); + } + + @PutMapping() + public ResponseEntity updateScreening(@PathVariable int id, @RequestBody Screening screening) { + if(screening.getMovie() == null) { + throw new BadRequestException("Movie must be provided"); + } + Screening screeningToUpdate = this.screeningRepository.findById(id).orElseThrow( + () -> new NotFoundException("No screening with that ID found") + ); + screening.setId(screeningToUpdate.getId()); + return new ResponseEntity<>(this.screeningRepository.save(screening), HttpStatus.CREATED); + } + + @DeleteMapping() + public ResponseEntity deleteScreening(@RequestBody int id) { + Screening screeningToDelete = this.screeningRepository.findById(id).orElseThrow( + () -> new NotFoundException("No screening with that ID found") + ); + this.screeningRepository.delete(screeningToDelete); + return ResponseEntity.ok(screeningToDelete); + } +} diff --git a/src/main/java/com/booleanuk/api/cinema/controller/TicketController.java b/src/main/java/com/booleanuk/api/cinema/controller/TicketController.java new file mode 100644 index 00000000..a8189ccc --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/controller/TicketController.java @@ -0,0 +1,58 @@ +package com.booleanuk.api.cinema.controller; + +import com.booleanuk.api.cinema.Customer; +import com.booleanuk.api.cinema.DTO.NotFoundException; +import com.booleanuk.api.cinema.DTO.TicketDTO; +import com.booleanuk.api.cinema.Screening; +import com.booleanuk.api.cinema.Ticket; +import com.booleanuk.api.cinema.repository.CustomerRepository; +import com.booleanuk.api.cinema.repository.ScreeningRepository; +import com.booleanuk.api.cinema.repository.TicketRepository; +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.util.List; + +@RestController +@RequestMapping("/customers/{customerId}/screenings/{screeningId}") +public class TicketController { + + private final TicketRepository ticketRepository; + private final CustomerRepository customerRepository; + private final ScreeningRepository screeningRepository; + + @Autowired + public TicketController(ScreeningRepository screeningRepository, TicketRepository ticketRepository, CustomerRepository customerRepository){ + this.ticketRepository = ticketRepository; + this.customerRepository = customerRepository; + this.screeningRepository = screeningRepository; + } + + @GetMapping + public List getAllTickets(){ + return this.ticketRepository.findAll(); + } + + @PostMapping + public ResponseEntity createTicket(@PathVariable int customerId, @PathVariable int screeningId, @RequestBody TicketDTO ticketDTO) { + Customer customer = this.customerRepository.findById(customerId).orElseThrow( + () -> new NotFoundException("No customer with that ID found") + ); + Screening screening = this.screeningRepository.findById(screeningId).orElseThrow( + () -> new NotFoundException("No screening with that ID found") + ); + + Ticket newTicket = new Ticket(); + newTicket.setNumSeats(ticketDTO.getNumSeats()); + newTicket.setScreening(screening); + newTicket.setCustomer(customer); + newTicket.setStartsAt(screening.getStartsAt()); + return new ResponseEntity<>(this.ticketRepository.save(newTicket), HttpStatus.CREATED); + } +} + + + + 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..4801007b --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/repository/CustomerRepository.java @@ -0,0 +1,10 @@ + +package com.booleanuk.api.cinema.repository; + +import 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/repository/MovieRepository.java b/src/main/java/com/booleanuk/api/cinema/repository/MovieRepository.java new file mode 100644 index 00000000..f92987ec --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/repository/MovieRepository.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.cinema.repository; + +import 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/repository/ScreeningRepository.java b/src/main/java/com/booleanuk/api/cinema/repository/ScreeningRepository.java new file mode 100644 index 00000000..3a182f3c --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/repository/ScreeningRepository.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.cinema.repository; + +import com.booleanuk.api.cinema.Screening; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ScreeningRepository extends JpaRepository { +} 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..acbd217d --- /dev/null +++ b/src/main/java/com/booleanuk/api/cinema/repository/TicketRepository.java @@ -0,0 +1,10 @@ + +package com.booleanuk.api.cinema.repository; + +import com.booleanuk.api.cinema.Ticket; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TicketRepository extends JpaRepository { +} + + 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