Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sis 39 #19

Merged
merged 7 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import jakarta.validation.Valid;

import sg.com.smartinventory.entities.Customer;
import sg.com.smartinventory.entities.Review;
// import sg.com.smartinventory.entities.Review;
import sg.com.smartinventory.services.CustomerService;

Expand Down Expand Up @@ -45,6 +46,13 @@ public ResponseEntity<Customer> createCustomer(@Valid @RequestBody Customer cust
return new ResponseEntity<>(newCustomer, HttpStatus.CREATED);
}

@PostMapping("/{id}/reviews")
public ResponseEntity<Review> addReviewToCustomer(@PathVariable long id, @RequestBody Review review) {
// TODO: process POST request
Review newReview = customerService.addReviewToCustomer(id, review);
return new ResponseEntity<>(newReview, HttpStatus.OK);
}

// READ (all)
@GetMapping("")
public ResponseEntity<ArrayList<Customer>> getAllCustomers() {
Expand All @@ -59,10 +67,16 @@ public ResponseEntity<Customer> getCustomer(@PathVariable long id) {
return new ResponseEntity<>(foundCustomer, HttpStatus.OK);
}

// READ (by name CONTAINS)
@GetMapping("/search")
public ResponseEntity<ArrayList<Customer>> searchCustomer(@RequestParam String firstName) {
ArrayList<Customer> customers = customerService.searchCustomer(firstName);
return new ResponseEntity<>(customers, HttpStatus.OK);
}

// UPDATE
@PutMapping("/{id}")
public ResponseEntity<Customer> updateCustomer(@PathVariable long id, @RequestBody Customer customer) {
// TODO: process PUT request
Customer updatedCustomer = customerService.updateCustomer(id, customer);
return new ResponseEntity<>(updatedCustomer, HttpStatus.OK);
}
Expand All @@ -71,7 +85,7 @@ public ResponseEntity<Customer> updateCustomer(@PathVariable long id, @RequestBo
@DeleteMapping("/{id}")
public ResponseEntity<HttpStatus> deleteCustomer(@PathVariable long id) {
customerService.deleteCustomer(id);
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}

// // Nested route - Add review to customer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,8 @@ public ReviewController(ReviewService reviewService) {
this.reviewService = reviewService;
}

// CREATE.
@PostMapping("")
public ResponseEntity<Review> createReview(@Valid @RequestBody Review review) {
// if(bindingResult.hasErrors()) {
// return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
// }

Review newReview = reviewService.createReview(review);
return new ResponseEntity<>(newReview, HttpStatus.CREATED);
}
// - - - NO POST HERE, due to data integrity with Customer FK - - -
// @PostMapping("")...

// READ (GET ALL).
@GetMapping("")
Expand Down
17 changes: 4 additions & 13 deletions src/main/java/sg/com/smartinventory/entities/Customer.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,25 +60,16 @@ public class Customer {
@Column(name = "email")
private String email;

// Uni-directional One to Many mapping -> One Customer (Parent) can have many
// Reviews (Child). The extra column 'customer_id' will be created on the many
// side of the relationship, that is, in the Review table. The cascade attribute
// is set to CascadeType.ALL to cascade all operations (e.g., save, update,
// delete) to the associated Review entities. The @JoinColumn annotation is used
// to specify the foreign key column (customer_id) in the Review table that
// establishes the relationship. Thus, it specifies the foreign key column in
// the child entity’s table that refers to the parent entity. The ‘mappedBy’
// attribute is not used in a unidirectional relationship as it’s specific to
// bidirectional relationships.
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "customer_id", referencedColumnName = "id")
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)

private List<Review> reviews;

public Customer() {
}

// Define Constructor for DataLoader.
public Customer(String firstName, String lastName, String country, String address, int postalCode, int phoneNumber,
public Customer(String firstName, String lastName, String country, String address, int postalCode,
int phoneNumber,
String email) {
this();

Expand Down
6 changes: 3 additions & 3 deletions src/main/java/sg/com/smartinventory/entities/Product.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ public class Product {
// the child entity’s table that refers to the parent entity. The ‘mappedBy’
// attribute is not used in a unidirectional relationship as it’s specific to
// bidirectional relationships.
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "product_id", referencedColumnName = "id")
private List<Review> reviews;
// @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
// @JoinColumn(name = "product_id", referencedColumnName = "id")
// private List<Review> reviews;

public Product() {
}
Expand Down
27 changes: 18 additions & 9 deletions src/main/java/sg/com/smartinventory/entities/Review.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package sg.com.smartinventory.entities;

import org.springframework.stereotype.Component;

import com.fasterxml.jackson.annotation.JsonBackReference;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.validation.constraints.Min;
Expand All @@ -14,6 +19,7 @@
import lombok.Getter;
import lombok.Setter;

@Component // @Component annotation required to inject into DataLoader
@Getter
@Setter
@Builder
Expand All @@ -35,14 +41,20 @@ public class Review {
@Column(name = "rating")
private int rating;

@Min(value = 1, message = "Customer ID should start from 1. ")
@Column(name = "customer_id")
private long customerId; // FK. PostgreSQL bigserial data type.

@Min(value = 1, message = "Product ID should start from 1. ")
// @Min(value = 1, message = "Product ID should start from 1. ")
@Column(name = "product_id")
private long productId; // FK. PostgreSQL bigserial data type.

// @ManyToOne Customer -> Many Reviews can be linked to 1 Customer
// @Min(value = 1, message = "Customer ID should start from 1. ")
@JsonBackReference
@ManyToOne(optional = false)
@JoinColumn(name = "customer_id", referencedColumnName = "id")
private Customer customer;

// @ManyToOne Product -> Many Reviews can be linked to 1 Product
// TODO

public Review() {
}

Expand All @@ -53,11 +65,8 @@ public Review(String category, String reviewContent, int rating, long customerId
this.category = category;
this.reviewContent = reviewContent;
this.rating = rating;
this.customerId = customerId;
// this.customerId = customerId;
this.productId = productId;
}

// @ManyToOne Product -> Many Reviews can be linked to 1 Product

// @ManyToOne Customer -> Many Reviews can be linked to 1 Customer
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public interface CustomerRepository extends JpaRepository<Customer, Long> {
// List<Customer> findById(long id);

// Custom query to find all customers with a certain first name.
List<Customer> findByFirstName(String firstName);
List<Customer> findByFirstNameContaining(String firstName);

// Custom query to find all customers with a certain last name.
List<Customer> findByLastName(String lastName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,41 @@
import org.springframework.stereotype.Service;

import sg.com.smartinventory.entities.Customer;
import sg.com.smartinventory.entities.Review;
// import sg.com.smartinventory.entities.Review;
import sg.com.smartinventory.exceptions.CustomerNotFoundException;
import sg.com.smartinventory.repositories.CustomerRepository;
import sg.com.smartinventory.repositories.ReviewRepository;
import sg.com.smartinventory.services.CustomerService;

@Service
public class CustomerServiceImpl implements CustomerService {
private CustomerRepository customerRepository;
private ReviewRepository reviewRepository;

// @Autowired
public CustomerServiceImpl(CustomerRepository customerRepository) {
public CustomerServiceImpl(CustomerRepository customerRepository, ReviewRepository reviewRepository) {
this.customerRepository = customerRepository;
this.reviewRepository = reviewRepository;
}

// - - - POST METHODS
@Override
public Customer createCustomer(Customer customer) {
Customer newCustomer = customerRepository.save(customer);

return newCustomer;
}

public Review addReviewToCustomer(long id, Review review) {
Customer customer = customerRepository.findById(id).orElseThrow(() -> new CustomerNotFoundException(id));
review.setCustomer(customer);
Review newReview = reviewRepository.save(review);
return newReview;
}

// - - - GET METHODS
@Override
public Customer getCustomer(Long id) {
// Optional<Customer> optionalCustomer = customerRepository.findById(id);
// if(optionalCustomer.isPresent()) {
// Customer foundCustomer = optionalCustomer.get();
// return foundCustomer;
// }
// throw new CustomerNotFoundException(id);
return customerRepository.findById(id).orElseThrow(() -> new CustomerNotFoundException(id));
}

Expand All @@ -44,6 +50,14 @@ public ArrayList<Customer> getAllCustomers() {
return (ArrayList<Customer>) allCustomers;
}

// searches for first name that contains search term
@Override
public ArrayList<Customer> searchCustomer(String firstName) {
List<Customer> customers = customerRepository.findByFirstNameContaining(firstName);
return (ArrayList<Customer>) customers;
}

// - - - PUT METHODS
@Override
public Customer updateCustomer(Long id, Customer customer) {
// Retrieve the customer from the database.
Expand All @@ -63,8 +77,13 @@ public Customer updateCustomer(Long id, Customer customer) {
return customerRepository.save(customerToUpdate);
}

// - - - DELETE METHODS
@Override
public void deleteCustomer(long id) {
// findById method allows deleteCustomer to throw exception if no id of
// such type is avail to be deleted i.e response will be 404 (Expected) instead
// of 204, to tell client that resource not found
customerRepository.findById(id).orElseThrow(() -> new CustomerNotFoundException(id));
customerRepository.deleteById(id);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ public Review updateReview(Long id, Review review) {
reviewToUpdate.setCategory(review.getCategory());
reviewToUpdate.setReviewContent(review.getReviewContent());
reviewToUpdate.setRating(review.getRating());
reviewToUpdate.setCustomerId(review.getCustomerId());
reviewToUpdate.setProductId(review.getProductId());

// Save the updated review back to the database.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@

import sg.com.smartinventory.entities.Customer;
// import sg.com.smartinventory.entities.Review;
import sg.com.smartinventory.entities.Review;

public interface CustomerService {
Customer createCustomer(Customer customer);

Review addReviewToCustomer(long id, Review review);

Customer getCustomer(Long id);

ArrayList<Customer> searchCustomer(String name);

ArrayList<Customer> getAllCustomers();

Customer updateCustomer(Long id, Customer customer);
Expand Down
Loading
Loading