최신순, 낮은 가격순, 주문 횟수 많은 순으로 상품 조회하기 기능의 구조가 동일하여 하나의 요청 형식으로 수정했다. 요청할 때 page, size, sort 형식을 함께 보내면 그에 맞는 결과를 가져온다.
ProductController
@GetMapping("/list")
public ResponseEntity<List<ProductInfo>> getLatestProducts(Pageable pageable) {
return ResponseEntity.ok(productService.getProducts(pageable));
}
ProductService
public List<ProductInfo> getProducts(Pageable pageable) {
Page<Product> products = productRepository.findAll(pageable);
return ProductInfo.toList(products);
}
상품 id를 받으면 상품 상세 정보를 불러오는 기능 구현했다.
ProductController
@GetMapping("/info/{id}")
public ResponseEntity<ProductInfo> getProductInfo(
@PathVariable long id
) {
return ResponseEntity.ok(productService.getProductInfo(id));
}
ProductService
public ProductInfo getProductInfo(Long id) {
Product product = productRepository.findById(id)
.orElseThrow(() -> new CustomException(ErrorCode.PRODUCT_NOT_FOUND));
return ProductInfo.from(product);
}
장바구니 정보를 담을 Cart 엔티티를 생성했다.
Cart
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
@Entity
public class Cart {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "customer_id")
@ToString.Exclude
private Customer customer;
@ManyToOne
@JoinColumn(name = "product_id")
@ToString.Exclude
private Product product;
private Integer quantity;
}
JWT 토큰에 담긴 Customer Id로 Customer를 조회하고, 장바구니 담기할 때 Product가 존재하는지 확인한다. 해당 상품의 남은 수량과 장바구니에 담는 수량을 비교하여 장바구니 수량이 더 많으면 Custom Error가 발생하게 했다. 만약 해당 Customer Id, Product Id를 가지고 있는 장바구니가 존재하면 해당 장바구니에서 상품 수량을 추가하는 기능을 구현했다.
CartController
@PostMapping
@PreAuthorize("hasRole('CUSTOMER')")
public ResponseEntity<String> registerProduct(
@RequestHeader(name = HttpHeaders.AUTHORIZATION) String token,
@RequestBody AddCartForm form
) {
cartService.addCart(token, form);
return ResponseEntity.ok(ADD_CART_SUCCESS);
}
CartService
public void addCart(String token, AddCartForm form) {
UserVo vo = provider.getUserVo(token);
Customer customer = customerRepository.findById(vo.getId())
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
Product product = productRepository.findById(form.getProductId())
.orElseThrow(() -> new CustomException(ErrorCode.PRODUCT_NOT_FOUND));
Optional<Cart> optionalExistCart = cartRepository.findByCustomerIdAndProductId(
vo.getId(),
form.getProductId());
if (optionalExistCart.isPresent()) {
Cart existCart = optionalExistCart.get();
Integer totalQuantity = existCart.getQuantity() + form.getQuantity();
if (!checkQuantity(product.getQuantity(), totalQuantity)) {
throw new CustomException(ErrorCode.NOT_ENOUGH_QUANTITY);
}
existCart.setQuantity(totalQuantity);
cartRepository.save(existCart);
} else {
if (!checkQuantity(product.getQuantity(), form.getQuantity())) {
throw new CustomException(ErrorCode.NOT_ENOUGH_QUANTITY);
}
Cart cart = Cart.builder()
.customer(customer)
.product(product)
.quantity(form.getQuantity())
.build();
cartRepository.save(cart);
}
}
CartController
@PutMapping
@PreAuthorize("hasRole('CUSTOMER')")
public ResponseEntity<String> editCart(
@RequestHeader(name = HttpHeaders.AUTHORIZATION) String token,
@RequestBody EditCartForm form
) {
cartService.editCart(token, form);
return ResponseEntity.ok(EDIT_CART_SUCCESS);
}
@ApiOperation(value = "하나의 상품을 장바구니에서 제거")
@DeleteMapping("/item/{id}")
@PreAuthorize("hasRole('CUSTOMER')")
public ResponseEntity<String> deleteCartItem(
@RequestHeader(name = HttpHeaders.AUTHORIZATION) String token,
@Parameter(name = "id", description = "장바구니 아이디")
@PathVariable("id") long id
) {
cartService.deleteCartItem(token, id);
return ResponseEntity.ok(DELETE_CART_ITEM_SUCCESS);
}
@ApiOperation(value = "장바구니 전체 삭제")
@DeleteMapping("/items")
@PreAuthorize("hasRole('CUSTOMER')")
public ResponseEntity<String> deleteAllCart(
@RequestHeader(name = HttpHeaders.AUTHORIZATION) String token
) {
long cnt = cartService.deleteAllCart(token);
return ResponseEntity.ok(cnt + "개의 상품 " + DELETE_ALL_CART_SUCCESS);
}
CartService
@Override
public void editCart(String token, EditCartForm form) {
Customer customer = getCustomerFromToken(token);
Product product = productRepository.findById(form.getProductId())
.orElseThrow(() -> new CustomException(ErrorCode.PRODUCT_NOT_FOUND));
Cart cart = cartRepository.findByCustomerIdAndProductId(customer.getId(), product.getId())
.orElseThrow(() -> new CustomException(ErrorCode.CART_NOT_FOUND));
if (!checkQuantity(product.getQuantity(), form.getQuantity())) {
throw new CustomException(ErrorCode.NOT_ENOUGH_QUANTITY);
}
cart.setQuantity(form.getQuantity());
cartRepository.save(cart);
}
@Override
public void deleteCartItem(String token, Long productId) {
Customer customer = getCustomerFromToken(token);
Product product = productRepository.findById(productId)
.orElseThrow(() -> new CustomException(ErrorCode.PRODUCT_NOT_FOUND));
Cart cart = cartRepository.findByCustomerIdAndProductId(customer.getId(), product.getId())
.orElseThrow(() -> new CustomException(ErrorCode.CART_NOT_FOUND));
cartRepository.delete(cart);
}
@Override
@Transactional
public long deleteAllCart(String token) {
Customer customer = getCustomerFromToken(token);
Long cnt = cartRepository.deleteByCustomerId(customer.getId());
return cnt;
}