Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 39 additions & 26 deletions src/main/java/com/back/domain/cart/entity/Cart.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,43 +126,49 @@ public boolean isFundingCart() {
return this.cartType == CartType.FUNDING;
}

// 유효한 장바구니 아이템인지 확인
// 유효한 장바구니 아이템인지 확인 (null-safe)
public boolean isValid() {
// 수량 검증
if (this.quantity <= 0) {
// 1) 수량 검증 (null 또는 1 미만이면 무효)
if (this.quantity == null || this.quantity <= 0) {
return false;
}


// 2) 펀딩 장바구니 검증
if (isFundingCart()) {
// 펀딩 장바구니 검증
if (this.funding == null) {
return false;
}
// fundingStock이 설정되어 있으면 그것을 기준으로, 없으면 funding의 stock 사용
int availableStock = (this.fundingStock != null) ? this.fundingStock : this.funding.getStock();
return this.quantity <= availableStock;
} else {
// 일반 장바구니 검증
if (this.product == null) {
return false;
}

// 상품이 삭제되지 않았고 재고가 있는지
if (this.product.isDeleted() || this.product.getStock() <= 0) {
Integer fundingStockFromEntity = this.funding.getStock();
int availableStock = (this.fundingStock != null)
? this.fundingStock
: (fundingStockFromEntity != null ? fundingStockFromEntity : 0);

if (availableStock <= 0) {
return false;
}

// 일반 재고 확인
return this.quantity <= this.product.getStock();
return this.quantity <= availableStock;
}

// 3) 일반 장바구니 검증
if (this.product == null) {
return false;
}
if (this.product.isDeleted()) {
return false;
}
Integer productStock = this.product.getStock();
if (productStock == null || productStock <= 0) {
return false;
}
return this.quantity <= productStock;
}

// 총 가격 계산
// 총 가격 계산 (null-safe)
public int getTotalPrice() {
int qty = (this.quantity != null && this.quantity > 0) ? this.quantity : 0;
int unitPrice;

if (isFundingCart()) {
// 펀딩 장바구니: fundingPrice 사용
if (this.fundingPrice != null) {
unitPrice = this.fundingPrice;
} else if (this.funding != null) {
Expand All @@ -171,14 +177,21 @@ public int getTotalPrice() {
return 0;
}
} else {
// 일반 장바구니: Product 가격 사용
if (this.product == null) {
return 0;
}
unitPrice = this.product.getDiscountPrice();
Integer discount = this.product.getDiscountPrice();
Integer basePrice = this.product.getPrice();
if (discount != null) {
unitPrice = discount;
} else if (basePrice != null) {
unitPrice = basePrice;
} else {
return 0;
}
}
return unitPrice * this.quantity;

return unitPrice * qty;
}

// ===== 도메인 메서드 (선택 상태 조회) =====
Expand Down
27 changes: 26 additions & 1 deletion src/main/java/com/back/domain/cart/service/CartService.java
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,9 @@ public void validateCartItemsForOrder(User user, boolean isFullOrder) {
throw new ServiceException("CART_EMPTY", "주문할 장바구니 아이템이 없습니다.");
}

// 레거시 데이터 보정 (펀딩 price/stock 누락 대비)
cartItems.forEach(this::normalizeCartFields);

// 각 아이템의 유효성 검증
for (Cart cart : cartItems) {
if (!cart.isValid()) {
Expand All @@ -319,13 +322,35 @@ public void validateCartItemsForOrder(User user, boolean isFullOrder) {
}
}

private void normalizeCartFields(Cart cart) {
if (cart.isFundingCart() && cart.getFunding() != null) {
if (cart.getFundingPrice() == null) {
cart.updateFundingInfo(
cart.getFundingId(),
(int) cart.getFunding().getPrice(),
cart.getFundingStock()
);
}
if (cart.getFundingStock() == null) {
cart.updateFundingInfo(
cart.getFundingId(),
cart.getFundingPrice(),
cart.getFunding().getStock()
);
}
}
}

/**
* 장바구니 총 금액 계산 (전체/선택)
*/
public Integer calculateTotalAmount(User user, boolean isFullOrder) {
List<Cart> cartItems = isFullOrder ?
cartRepository.findByUserWithProduct(user) :
cartRepository.findByUserAndIsSelectedTrue(user);
cartRepository.findByUserAndIsSelectedTrueWithProduct(user);

// 레거시 보정(펀딩 price/stock 누락 대비)
cartItems.forEach(this::normalizeCartFields);

return cartItems.stream()
.filter(Cart::isValid)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,12 +560,12 @@ void validateCartItemsForOrder_SelectedOrder_Success() {
// Given
testNormalCart.select();
List<Cart> selectedCarts = Arrays.asList(testNormalCart);
given(cartRepository.findByUserAndIsSelectedTrue(testUser)).willReturn(selectedCarts);
given(cartRepository.findByUserAndIsSelectedTrueWithProduct(testUser)).willReturn(selectedCarts);

// When & Then
cartService.validateCartItemsForOrder(testUser, false);

verify(cartRepository).findByUserAndIsSelectedTrue(testUser);
verify(cartRepository).findByUserAndIsSelectedTrueWithProduct(testUser);
}

@Test
Expand Down Expand Up @@ -601,14 +601,14 @@ void calculateTotalAmount_SelectedOrder_Success() {
// Given
testNormalCart.select();
List<Cart> selectedCarts = Arrays.asList(testNormalCart);
given(cartRepository.findByUserAndIsSelectedTrue(testUser)).willReturn(selectedCarts);
given(cartRepository.findByUserAndIsSelectedTrueWithProduct(testUser)).willReturn(selectedCarts);

// When
Integer result = cartService.calculateTotalAmount(testUser, false);

// Then
assertThat(result).isNotNull();
verify(cartRepository).findByUserAndIsSelectedTrue(testUser);
verify(cartRepository).findByUserAndIsSelectedTrueWithProduct(testUser);
}

@Test
Expand Down