Skip to content

Commit

Permalink
Merge pull request #45 from THEGOODs-repo/feature/44
Browse files Browse the repository at this point in the history
[feature/44] ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์˜ต์…˜ ์ˆ˜์ • API ๊ตฌํ˜„
  • Loading branch information
Eunjin3395 authored Feb 5, 2024
2 parents 32d6d4f + 9473b6f commit 367ab45
Show file tree
Hide file tree
Showing 11 changed files with 196 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,51 @@ 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);

// ์—”ํ‹ฐํ‹ฐ ์ €์žฅ
cartRepository.save(cart);
}
}

@Override
public Cart updateCart(CartRequestDTO.cartUpdateDTO request, Member member) {
// cart ์กด์žฌ ์—ฌ๋ถ€ ๊ฒ€์ฆ์€ annotation์—์„œ ์ง„ํ–‰
Cart cart = cartRepository.findById(request.getCartId()).get();

// ํ•ด๋‹น cart ๋‚ด์—ญ์„ ์ˆ˜์ •ํ•  ๊ถŒํ•œ ์žˆ๋Š”์ง€ ๊ฒ€์ฆ
if (!cart.getMember().equals(member)) {
throw new OrderHandler(ErrorStatus.NOT_CART_OWNER);
}

// ์žฌ๊ณ  ์ˆ˜๋Ÿ‰๊ณผ ๋น„๊ต
if (!cart.getItem().getItemOptionList().isEmpty()) { // ์ƒํ’ˆ ์˜ต์…˜์ด ์žˆ๋Š” ๊ฒฝ์šฐ
if (request.getAmount() > cart.getItemOption().getStock()) {
throw new OrderHandler(ErrorStatus.LACK_OF_STOCK);
}
} else {
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;
}
}
26 changes: 22 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,26 @@ public ApiResponse<String> add(@RequestBody @Valid CartRequestDTO.cartAddDTO req
return ApiResponse.onSuccess("์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋‹ด๊ธฐ ์„ฑ๊ณต");
}

@PutMapping
@Operation(summary = "์žฅ๋ฐ”๊ตฌ๋‹ˆ ์˜ต์…˜ ์ˆ˜์ • API", description = "ํ•ด๋‹น ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋‚ด์—ญ์˜ ๋‹ด์€ ์ˆ˜๋Ÿ‰์„ ์ˆ˜์ •ํ•˜๋Š” API ์ž…๋‹ˆ๋‹ค.")
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, ์„ฑ๊ณต"),
})
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 367ab45

Please sign in to comment.