[ SourceCode 참고]

https://github.com/jjangsky/Testing-study

요구 사항

Entity 설정

@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Stock extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String productNumber;
    private int quantity;
    
}

Production Code

주문 생성 시, 재고를 관리하는 기능이므로 이전에 생성한 주문 Service 로직을 수정한다.

[ 전체 코드 ]

public OrderResponse createOrder(OrderCreateRequest request, 
																			LocalDateTime registeredDateTime) {
        List<String> productNumbers = request.getProductNumbers();

        // Prodcut
        List<Product> products = findProductsBy(productNumbers);

        // 1. 재고 차감 체크가 필요한 상품들 Filter
        List<String> stockProductNumbers =  products.stream()
                .filter(product -> ProductType.containsStockType(product.getType()))
                .map(Product::getProductNumber)
                .collect(Collectors.toList());

        // 2. 재고 엔티티 조회
        List<Stock> stocks = stockRepository
															        .findAllByProductNumberIn(stockProductNumbers);
        Map<String, Stock> stockMap = stocks.stream()
                .collect(Collectors.toMap(Stock::getProductNumber, s -> s));

        // 3. 상품별 Counting
        Map<String, Long> producCountingMap = stockProductNumbers.stream()
                .collect(Collectors.groupingBy(p -> p, Collectors.counting()));

        // 4. 재고 차감 시도(중복 제거 필요함)
        for(String stockProductNumber : new HashSet<>(stockProductNumbers)){
            Stock stock = stockMap.get(stockProductNumber);
            int quantity = producCountingMap.get(stockProductNumber).intValue();
            if(stock.isQuantityLessThan(quantity)){
                // 재고가 부족한 경우 예외 처리
                throw new IllegalArgumentException("재고가 부족한 상품이 있습니다.");
            }
            stock.deductQuantity(quantity);
        }
        
        Order order = Order.create(products, registeredDateTime);
        Order savedOrder = orderRepository.save(order);
        return OrderResponse.of(savedOrder);
    }
  1. 재고 차감 체크가 필요한 상품들 Filter

요구 사항에서는 병 음료와 베이커리만 재고를 차감해야 하기 때문에 이전에 조회한 상품 목록에서 해당 목록만 따로 추출 해야한다.

// 상품 정보
List<Product> products = findProductsBy(productNumbers);

List<String> stockProductNumbers =  products.stream()
            .filter(product -> ProductType.containsStockType(product.getType()))
            .map(Product::getProductNumber)
            .collect(Collectors.toList());