Skip to content

Commit

Permalink
✨ Feat: 장바구니 옵션 수정 API 구현 및 장바구니 담기 API 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
Eunjin3395 committed Feb 5, 2024
1 parent 32d6d4f commit b07b383
Show file tree
Hide file tree
Showing 11 changed files with 186 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ public enum ErrorStatus implements BaseErrorCode {
ORDER_ITEM_UPDATE_FAIL(HttpStatus.BAD_REQUEST, "ORDER4008", "주문 상품 정보 변경이 불가합니다."),
NULL_AMOUNT_ERROR(HttpStatus.BAD_REQUEST, "ORDER4009", "주문 수량은 null일 수 없습니다."),

// 장바구니 관련 에러
CART_NOT_FOUND(HttpStatus.NOT_FOUND, "CART4001", "해당 장바구니 내역을 찾을 수 없습니다."),
NOT_CART_OWNER(HttpStatus.BAD_REQUEST, "CART4002", "본인의 장바구니 내역이 아닙니다. 접근할 수 없습니다."),

// test
TEMP_EXCEPTION(HttpStatus.BAD_REQUEST, "TEMP4001", "테스트"),

Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/umc/TheGoods/domain/order/Cart.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,9 @@ public void setItemOption(ItemOption itemOption) {
this.itemOption = itemOption;
itemOption.getCartList().add(this);
}

public Cart updateAmount(Integer amount) {
this.amount = amount;
return this;
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/umc/TheGoods/repository/cart/CartRepository.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
package com.umc.TheGoods.repository.cart;

import com.umc.TheGoods.domain.item.Item;
import com.umc.TheGoods.domain.item.ItemOption;
import com.umc.TheGoods.domain.member.Member;
import com.umc.TheGoods.domain.order.Cart;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface CartRepository extends JpaRepository<Cart, Long> {

Optional<Cart> findByMemberAndItemAndItemOption(Member member, Item item, ItemOption itemOption);

Optional<Cart> findByMemberAndItem(Member member, Item item);

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.umc.TheGoods.service.CartService;

import com.umc.TheGoods.domain.member.Member;
import com.umc.TheGoods.domain.order.Cart;
import com.umc.TheGoods.web.dto.cart.CartRequestDTO;

public interface CartCommandService {

void addCart(CartRequestDTO.cartAddDTO request, Member member);

Cart updateCart(CartRequestDTO.cartUpdateDTO request, Member member);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
Expand Down Expand Up @@ -50,14 +51,25 @@ public void addCart(CartRequestDTO.cartAddDTO request, Member member) {
throw new OrderHandler(ErrorStatus.LACK_OF_STOCK);
}

// cart 테이블에 해당 장바구니 내역 이미 존재하면, 해당 내역의 담은 수량만 업데이트하는 부분 추가 필요

// cart 엔티티 생성 및 연관관계 매핑
Cart cart = CartConverter.toCart(cartOptionAddDTO.getAmount());
cart.setMember(member);
cart.setItem(item);
cart.setItemOption(itemOption);
return cart;
// cart 테이블에 해당 장바구니 내역 이미 존재하면, 해당 내역의 담은 수량만 업데이트
Optional<Cart> existCart = cartRepository.findByMemberAndItemAndItemOption(member, item, itemOption);
if (!existCart.isEmpty()) { // 장바구니 내역 이미 존재하는 경우
// 재고 수량과 비교
if (cartOptionAddDTO.getAmount() + existCart.get().getAmount() > itemOption.getStock()) {
throw new OrderHandler(ErrorStatus.LACK_OF_STOCK);
}

// 장바구니 내역의 수량 업데이트
existCart.get().updateAmount(existCart.get().getAmount() + cartOptionAddDTO.getAmount());
return existCart.get();
} else { // 신규 장바구니 내역 생성
// cart 엔티티 생성 및 연관관계 매핑
Cart cart = CartConverter.toCart(cartOptionAddDTO.getAmount());
cart.setMember(member);
cart.setItem(item);
cart.setItemOption(itemOption);
return cart;
}
}).collect(Collectors.toList());

// 엔티티 저장
Expand All @@ -79,16 +91,45 @@ public void addCart(CartRequestDTO.cartAddDTO request, Member member) {
throw new OrderHandler(ErrorStatus.LACK_OF_STOCK);
}

// cart 테이블에 해당 장바구니 내역 이미 존재하면, 해당 내역의 담은 수량만 업데이트하는 부분 추가 필요
Optional<Cart> existCart = cartRepository.findByMemberAndItem(member, item);
if (!existCart.isEmpty()) { // 장바구니 내역 이미 존재하는 경우
// 재고 수량과 비교
if (request.getAmount() + existCart.get().getAmount() > item.getStock()) {
throw new OrderHandler(ErrorStatus.LACK_OF_STOCK);
}

// 장바구니 내역의 수량 업데이트
existCart.get().updateAmount(request.getAmount());
} else { // 장바구니 내역 신규 생성

// cart 엔티티 생성 및 연관관계 매핑
Cart cart = CartConverter.toCart(request.getAmount());
cart.setMember(member);
cart.setItem(item);

// 엔티티 저장
cartRepository.save(cart);
}


}
}

// cart 엔티티 생성 및 연관관계 매핑
Cart cart = CartConverter.toCart(request.getAmount());
cart.setMember(member);
cart.setItem(item);
@Override
public Cart updateCart(CartRequestDTO.cartUpdateDTO request, Member member) {
// cart 존재 여부 검증은 annotation에서 진행
Cart cart = cartRepository.findById(request.getCartId()).get();

// 엔티티 저장
cartRepository.save(cart);
// 해당 cart 내역을 수정할 권한 있는지 검증
if (!cart.getMember().equals(member)) {
throw new OrderHandler(ErrorStatus.NOT_CART_OWNER);
}

// 재고 수량과 비교
if (request.getAmount() > cart.getItem().getStock()) {
throw new OrderHandler(ErrorStatus.LACK_OF_STOCK);
}

return cart.updateAmount(request.getAmount());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.umc.TheGoods.service.CartService;

public interface CartQueryService {

boolean isExistCart(Long cartId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.umc.TheGoods.service.CartService;

import com.umc.TheGoods.repository.cart.CartRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class CartQueryServiceImpl implements CartQueryService {

private final CartRepository cartRepository;


@Override
public boolean isExistCart(Long cartId) {
return cartRepository.existsById(cartId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.umc.TheGoods.validation.annotation;

import com.umc.TheGoods.validation.validator.CartExistValidator;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = CartExistValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExistCart {
String message() default "해당 장바구니 내역을 찾을 수 없습니다.";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.umc.TheGoods.validation.validator;

import com.umc.TheGoods.apiPayload.code.status.ErrorStatus;
import com.umc.TheGoods.service.CartService.CartQueryService;
import com.umc.TheGoods.validation.annotation.ExistCart;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

@Component
@RequiredArgsConstructor
public class CartExistValidator implements ConstraintValidator<ExistCart, Long> {

private final CartQueryService cartQueryService;

@Override
public void initialize(ExistCart constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}

@Override
public boolean isValid(Long value, ConstraintValidatorContext context) {
boolean isValid = cartQueryService.isExistCart(value);
if (!isValid) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(ErrorStatus.CART_NOT_FOUND.getMessage()).addConstraintViolation();
}
return isValid;
}
}
22 changes: 18 additions & 4 deletions src/main/java/com/umc/TheGoods/web/controller/CartController.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

Expand Down Expand Up @@ -56,5 +53,22 @@ public ApiResponse<String> add(@RequestBody @Valid CartRequestDTO.cartAddDTO req
return ApiResponse.onSuccess("장바구니 담기 성공");
}

@PutMapping
public ApiResponse<String> update(@RequestBody @Valid CartRequestDTO.cartUpdateDTO request,
Authentication authentication) {
// 비회원인 경우 처리 불가
if (authentication == null) {
throw new MemberHandler(ErrorStatus._UNAUTHORIZED);
}

// request에서 member id 추출해 Member 엔티티 찾기
MemberDetail memberDetail = (MemberDetail) authentication.getPrincipal();
Member member = memberQueryService.findMemberById(memberDetail.getMemberId()).orElseThrow(() -> new MemberHandler(ErrorStatus.MEMBER_NOT_FOUND));

cartCommandService.updateCart(request, member);

return ApiResponse.onSuccess("장바구니 옵션 수정 성공");
}


}
13 changes: 13 additions & 0 deletions src/main/java/com/umc/TheGoods/web/dto/cart/CartRequestDTO.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.umc.TheGoods.web.dto.cart;

import com.umc.TheGoods.validation.annotation.ExistCart;
import com.umc.TheGoods.validation.annotation.ExistItem;
import com.umc.TheGoods.validation.annotation.ExistItemOption;
import lombok.Getter;
Expand Down Expand Up @@ -39,4 +40,16 @@ public static class cartOptionAddDTO {

}

@Getter
public static class cartUpdateDTO {
@NotNull
@ExistCart
Long cartId;

@Min(1)
@Max(100000)
@NotNull
Integer amount;
}

}

0 comments on commit b07b383

Please sign in to comment.