Skip to content

Commit aa9cbde

Browse files
authored
Merge pull request #185 from JA-yeong-eop-JA-moeu-JA/feat/#184-cart
✨ feat: 장바구니 상품 추가/수정 시 반환값 수정, 결제시간이 만료된 주문의 상태가 자동으로 변경되는 scheduler 추가
2 parents 409e41f + b30c08c commit aa9cbde

File tree

7 files changed

+77
-19
lines changed

7 files changed

+77
-19
lines changed

src/main/java/com/jajaja/domain/cart/controller/CartController.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,8 @@ public ApiResponse<CartResponseDto> getCart(@Auth Long memberId) {
3535
summary = "장바구니 아이템 추가 및 수정 API | by 엠마/신윤지",
3636
description = "장바구니에 아이템을 추가하거나 수량을 수정합니다.")
3737
@PostMapping("/products")
38-
public ApiResponse<String> addOrUpdateCartProduct(@Auth Long memberId, @RequestBody @Valid List<CartProductAddRequestDto> request) {
39-
cartCommandService.addOrUpdateCartProduct(memberId, request);
40-
return ApiResponse.onSuccess("성공적으로 장바구니에 상품이 추가/수정되었습니다.");
38+
public ApiResponse<CartResponseDto> addOrUpdateCartProduct(@Auth Long memberId, @RequestBody @Valid List<CartProductAddRequestDto> request) {
39+
return ApiResponse.onSuccess(cartCommandService.addOrUpdateCartProduct(memberId, request));
4140
}
4241

4342
@Operation(
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package com.jajaja.domain.cart.service;
22

33
import com.jajaja.domain.cart.dto.CartProductAddRequestDto;
4+
import com.jajaja.domain.cart.dto.CartResponseDto;
45

56
import java.util.List;
67

78
public interface CartCommandService {
8-
void addOrUpdateCartProduct(Long memberId, List<CartProductAddRequestDto> request);
9+
CartResponseDto addOrUpdateCartProduct(Long memberId, List<CartProductAddRequestDto> request);
910
void deleteCartProduct(Long memberId, Long productId, Long optionId);
1011
void deleteCartProducts(Long memberId, List<Long> cartProductIds);
1112
}

src/main/java/com/jajaja/domain/cart/service/CartCommandServiceImpl.java

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.jajaja.domain.cart.service;
22

3+
import com.jajaja.domain.cart.converter.CartConverter;
34
import com.jajaja.domain.cart.dto.CartProductAddRequestDto;
5+
import com.jajaja.domain.cart.dto.CartProductResponseDto;
6+
import com.jajaja.domain.cart.dto.CartResponseDto;
47
import com.jajaja.domain.cart.entity.Cart;
58
import com.jajaja.domain.cart.entity.CartProduct;
69
import com.jajaja.domain.cart.repository.CartProductRepository;
@@ -11,8 +14,12 @@
1114
import com.jajaja.domain.product.entity.ProductOption;
1215
import com.jajaja.domain.product.repository.ProductOptionRepository;
1316
import com.jajaja.domain.product.repository.ProductRepository;
17+
import com.jajaja.domain.product.service.ProductCommonService;
18+
import com.jajaja.domain.team.entity.enums.TeamStatus;
19+
import com.jajaja.domain.team.repository.TeamCommandRepository;
1420
import com.jajaja.global.apiPayload.code.status.ErrorStatus;
1521
import com.jajaja.global.apiPayload.exception.handler.CartHandler;
22+
import com.jajaja.global.common.dto.PriceInfoDto;
1623
import lombok.RequiredArgsConstructor;
1724
import lombok.extern.slf4j.Slf4j;
1825
import org.springframework.stereotype.Service;
@@ -27,38 +34,51 @@
2734
@Transactional
2835
public class CartCommandServiceImpl implements CartCommandService {
2936

30-
private final CartCommonService cartCommonService;
31-
private final CouponCommonService couponCommonService;
3237
private final CartProductRepository cartProductRepository;
3338
private final ProductRepository productRepository;
39+
private final TeamCommandRepository teamRepository;
3440
private final ProductOptionRepository productOptionRepository;
3541
private final MemberCouponRepository memberCouponRepository;
42+
private final CouponCommonService couponCommonService;
43+
private final ProductCommonService productCommonService;
44+
private final CartCommonService cartCommonService;
3645

3746
@Override
38-
public void addOrUpdateCartProduct(Long memberId, List<CartProductAddRequestDto> request) {
47+
public CartResponseDto addOrUpdateCartProduct(Long memberId, List<CartProductAddRequestDto> request) {
3948
Cart cart = cartCommonService.findCart(memberId);
40-
request.forEach(req -> {
49+
List<CartProductResponseDto> items = request.stream().map(req -> {
4150
log.info("[CartCommandService] 사용자 {}의 장바구니에 아이템 {} 추가/수정", memberId, req.productId());
4251

4352
CartOpterationContext context = prepareCartOperationContext(req.productId(), req.optionId());
4453

4554
Optional<CartProduct> existingItem = req.optionId() != null ? cartProductRepository.findByCartIdAndProductIdAndProductOptionId(cart.getId(), context.product().getId(), context.productOption.getId())
4655
: cartProductRepository.findByCartIdAndProductIdAndProductOptionIsNull(cart.getId(), context.product().getId());
4756

48-
existingItem.ifPresentOrElse(
49-
item -> {
57+
CartProduct cartProduct = existingItem
58+
.map(item -> {
5059
log.info("[CartCommandService] 기존 아이템 {}의 옵션과 수량을 변경합니다.", item.getId());
5160
item.update(context.productOption(), req.quantity());
52-
},
53-
() -> {
61+
return item;
62+
})
63+
.orElseGet(() -> {
5464
log.info("[CartCommandService] 장바구니에 새로 아이템 {}를 추가합니다.", req.productId());
5565
CartProduct newCartProduct = CartProduct.create(cart, context.product(), context.productOption(), req.quantity());
5666
cart.addCartProduct(newCartProduct);
57-
cartProductRepository.save( newCartProduct);
58-
}
59-
);
60-
});
67+
cartProductRepository.save(newCartProduct);
68+
return newCartProduct;
69+
});
70+
71+
boolean isTeamAvailable = teamRepository.existsByProductIdAndStatus(
72+
cartProduct.getProduct().getId(), TeamStatus.MATCHING);
73+
return CartProductResponseDto.of(cartProduct, productCommonService.calculateDiscountedPrice(cartProduct.getUnitPrice(), cartProduct.getProduct().getDiscountRate()), isTeamAvailable);
74+
}).toList();
75+
76+
PriceInfoDto priceInfo = cart.getCoupon() != null ?
77+
couponCommonService.calculateDiscount(cart, cart.getCoupon()) :
78+
PriceInfoDto.noDiscount(cart.calculateTotalAmount());
79+
6180
revalidateAppliedCouponIfExists(cart);
81+
return CartConverter.toCartResponseDto(cart, items, priceInfo);
6282
}
6383

6484
@Override

src/main/java/com/jajaja/domain/order/repository/OrderRepository.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22

33
import com.jajaja.domain.member.entity.Member;
44
import com.jajaja.domain.order.entity.Order;
5+
import com.jajaja.domain.order.entity.enums.OrderStatus;
56
import org.springframework.data.jpa.repository.EntityGraph;
67
import org.springframework.data.jpa.repository.JpaRepository;
78

9+
import java.time.LocalDateTime;
10+
import java.util.List;
811
import java.util.Optional;
912

1013
public interface OrderRepository extends JpaRepository<Order, Long>, OrderRepositoryCustom {
11-
1214
@EntityGraph(attributePaths = {"orderProducts", "orderProducts.product", "orderProducts.productOption", "team", "delivery"})
1315
Optional<Order> findById(Long id);
1416
Optional<Order> findByOrderId(String orderId);
1517
Boolean existsByMember(Member member);
18+
List<Order> findOrdersByOrderStatusAndCreatedAtBefore(OrderStatus orderStatus, LocalDateTime createdAtBefore);
1619
}

src/main/java/com/jajaja/domain/order/service/OrderCommandService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ public interface OrderCommandService {
1111
OrderPrepareResponseDto prepareOrder(Long memberId, OrderPrepareRequestDto request);
1212
OrderApproveResponseDto approveOrder(Long memberId, OrderApproveRequestDto request);
1313
OrderRefundResponseDto refundOrder(Long memberId, OrderRefundRequestDto request);
14-
void startShipping(Long orderId);
15-
}
14+
void expireOrder();
15+
void startShipping(Long orderId);}

src/main/java/com/jajaja/domain/order/service/OrderCommandServiceImpl.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.jajaja.global.config.RestTemplateConfig;
3737
import com.jajaja.global.config.TossPaymentsConfig;
3838

39+
import java.time.LocalDateTime;
3940
import java.util.*;
4041

4142
import lombok.RequiredArgsConstructor;
@@ -351,6 +352,18 @@ public OrderRefundResponseDto refundOrder(Long memberId, OrderRefundRequestDto r
351352
}
352353
}
353354

355+
@Override
356+
public void expireOrder() {
357+
orderRepository.findOrdersByOrderStatusAndCreatedAtBefore(OrderStatus.READY, LocalDateTime.now().minusMinutes(10))
358+
.forEach(order -> {
359+
if (order.getOrderStatus() == OrderStatus.READY) {
360+
order.updateStatus(OrderStatus.EXPIRED);
361+
order.getOrderProducts().forEach(orderProduct ->
362+
orderProduct.updateStatus(OrderStatus.EXPIRED));
363+
}
364+
});
365+
}
366+
354367
private Member findMember(Long memberId) {
355368
return memberRepository.findById(memberId)
356369
.orElseThrow(() -> new BadRequestException(ErrorStatus.MEMBER_NOT_FOUND));
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.jajaja.global.scheduler;
2+
3+
import com.jajaja.domain.order.service.OrderCommandService;
4+
import lombok.RequiredArgsConstructor;
5+
import lombok.extern.slf4j.Slf4j;
6+
import org.springframework.scheduling.annotation.Scheduled;
7+
import org.springframework.stereotype.Component;
8+
9+
@Slf4j
10+
@Component
11+
@RequiredArgsConstructor
12+
public class OrderExpireScheduler {
13+
14+
private final OrderCommandService orderCommandService;
15+
16+
@Scheduled(fixedDelay = 60000)
17+
public void expireOrders() {
18+
log.info("[OrderExpireScheduler] 만료된 주문 처리 스케줄러 시작");
19+
orderCommandService.expireOrder();
20+
log.info("[OrderExpireScheduler] 만료된 주문 처리 스케줄러 완료");
21+
}
22+
}

0 commit comments

Comments
 (0)