From d05ce9cc32fcf01a729a1dffb8175c52e986f933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=84=B1=ED=98=84?= Date: Tue, 22 Jul 2025 19:44:52 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[refactor]=20=EC=A3=BC=EB=AC=B8=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EA=B3=84=EC=82=B0=20=EC=B6=94=EC=83=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ecommerce/application/service/OrderService.kt | 13 ++++++------- .../kotlin/com/ecommerce/domain/coupon/Coupon.kt | 10 ++++++++++ .../main/kotlin/com/ecommerce/domain/order/Order.kt | 10 +++------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/ecommerce-application/src/main/kotlin/com/ecommerce/application/service/OrderService.kt b/ecommerce-application/src/main/kotlin/com/ecommerce/application/service/OrderService.kt index d9ef0df..33eaa00 100644 --- a/ecommerce-application/src/main/kotlin/com/ecommerce/application/service/OrderService.kt +++ b/ecommerce-application/src/main/kotlin/com/ecommerce/application/service/OrderService.kt @@ -5,6 +5,7 @@ import com.ecommerce.application.port.`in`.OrderUseCase import com.ecommerce.application.port.out.CouponPort import com.ecommerce.application.port.out.ItemPort import com.ecommerce.application.port.out.OrderPort +import com.ecommerce.domain.coupon.Coupon import com.ecommerce.domain.event.DeductStockEvent import com.ecommerce.domain.order.Order import org.springframework.context.ApplicationEventPublisher @@ -27,11 +28,7 @@ class OrderService( val items = itemPort.getItemsIn(orderItems.map { it.itemId }) items.forEach { it.isSelling() } - order.calculateOriginPrice(items) - - order.couponId?.let { - applyCouponTo(order) - } + order.calculatePrice(items, applyCouponTo(order)) order = orderPort.commandOrder(order) @@ -41,11 +38,13 @@ class OrderService( return order } - private fun applyCouponTo(order: Order) { + private fun applyCouponTo(order: Order): Coupon { + if (order.couponId == null) return Coupon.none() + val userCoupon = couponPort.findUserCouponBy(order.couponId!!, order.userId) couponPort.commandUserCoupon(userCoupon.use()) - order.calculateDiscountPrice(userCoupon.coupon) + return userCoupon.coupon } } \ No newline at end of file diff --git a/ecommerce-domain/src/main/kotlin/com/ecommerce/domain/coupon/Coupon.kt b/ecommerce-domain/src/main/kotlin/com/ecommerce/domain/coupon/Coupon.kt index 03444ad..1393dd1 100644 --- a/ecommerce-domain/src/main/kotlin/com/ecommerce/domain/coupon/Coupon.kt +++ b/ecommerce-domain/src/main/kotlin/com/ecommerce/domain/coupon/Coupon.kt @@ -23,11 +23,21 @@ class Coupon( override fun calculateDiscount(price: BigDecimal, discount: Long): BigDecimal { return BigDecimal.valueOf(discount) } + }, + NONE { + override fun calculateDiscount(price: BigDecimal, discount: Long): BigDecimal { + return BigDecimal.ZERO + } }; abstract fun calculateDiscount(price: BigDecimal, discount: Long): BigDecimal } + companion object { + fun none(): Coupon = + Coupon(0L, "none", DiscountType.NONE, 0L, 0, 0L) + } + fun calculateDiscount(price: BigDecimal): BigDecimal { return this.type.calculateDiscount(price, this.discount) } diff --git a/ecommerce-domain/src/main/kotlin/com/ecommerce/domain/order/Order.kt b/ecommerce-domain/src/main/kotlin/com/ecommerce/domain/order/Order.kt index 9a4e4cd..284b185 100644 --- a/ecommerce-domain/src/main/kotlin/com/ecommerce/domain/order/Order.kt +++ b/ecommerce-domain/src/main/kotlin/com/ecommerce/domain/order/Order.kt @@ -21,20 +21,16 @@ class Order( PENDING, COMPLETED, CANCEL } - fun calculateOriginPrice(items: List) { + fun calculatePrice(items: List, coupon: Coupon) { val quantityOfItem = this.orderItems.associate { it.itemId to BigDecimal.valueOf(it.quantity) } this.originPrice = items.sumOf { - it.price * quantityOfItem[it.id]!! + it.price * quantityOfItem[it.id]!! } - this.totalPrice = this.originPrice - } - - fun calculateDiscountPrice(coupon: Coupon) { this.discountPrice = coupon.calculateDiscount(this.originPrice) - this.totalPrice = this.originPrice - this.discountPrice + this.totalPrice = this.originPrice.minus(this.discountPrice) } fun complete(): Order { From ffda19ee1a6cc2159b610bbc05f170b868a5730f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=84=B1=ED=98=84?= Date: Tue, 22 Jul 2025 19:46:03 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[test]=20=EC=BF=A0=ED=8F=B0=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=EB=B3=84=20=EC=A3=BC=EB=AC=B8=20=EA=B8=88=EC=95=A1=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/ecommerce/domain/OrderTest.kt | 65 +++++++++---------- 1 file changed, 29 insertions(+), 36 deletions(-) diff --git a/ecommerce-domain/src/test/kotlin/com/ecommerce/domain/OrderTest.kt b/ecommerce-domain/src/test/kotlin/com/ecommerce/domain/OrderTest.kt index ad3295a..7b3485d 100644 --- a/ecommerce-domain/src/test/kotlin/com/ecommerce/domain/OrderTest.kt +++ b/ecommerce-domain/src/test/kotlin/com/ecommerce/domain/OrderTest.kt @@ -8,8 +8,7 @@ import com.ecommerce.domain.order.OrderItem import org.assertj.core.api.Assertions.* import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.DynamicTest -import org.junit.jupiter.api.TestFactory +import org.junit.jupiter.api.Test import java.math.BigDecimal class OrderTest { @@ -30,45 +29,39 @@ class OrderTest { } } - @DisplayName("주문 금액 계산") - @TestFactory - fun calculateOrderPrice(): List { + @DisplayName("쿠폰 타입별 주문 금액 계산") + @Test + fun calculateOrderPriceOnCouponType() { // given - val orderQuantity = 2L - val orderItem = items.map { OrderItem(null, it.id, orderQuantity) } - val order = Order(null, 1L, 1L, orderItem) - - var expectOriginPrice = BigDecimal.ZERO - - return listOf( - DynamicTest.dynamicTest("총 주문 금액이 계산 된다.") { - // when - order.calculateOriginPrice(items) - - // then - expectOriginPrice = items.sumOf { - it.price * (BigDecimal.valueOf(orderQuantity)) - } - assertThat(order.originPrice).isEqualTo(expectOriginPrice) - assertThat(order.originPrice).isEqualTo(order.totalPrice) - }, - DynamicTest.dynamicTest("할인 금액 계산") { - val coupon = Coupon(1L, "쿠폰 A", Coupon.DiscountType.RATE, 10L, 30, 10L) + val testCases = listOf( + Coupon(1L, "10% 할인", Coupon.DiscountType.RATE, 10L, 30, 10L), + Coupon(2L, "1,000원 할인", Coupon.DiscountType.AMOUNT, 1000L, 30, 10L), + Coupon(0L, "할인 없음", Coupon.DiscountType.NONE, 0L, 0, 0L) + ) - // when - order.calculateDiscountPrice(coupon) + testCases.forEach { coupon -> + // when + val orderQuantity = 2L + val orderItem = items.map { OrderItem(null, it.id, orderQuantity) } + val order = Order(null, 1L, 1L, orderItem) - // then - val expectDiscountPrice = expectOriginPrice * ( - BigDecimal.valueOf(coupon.discount).divide(BigDecimal.valueOf(100)) - ) - assertThat(order.discountPrice).isEqualTo(expectDiscountPrice) + order.calculatePrice(items, coupon) - val expectTotalPrice = expectOriginPrice - expectDiscountPrice - assertThat(expectOriginPrice).isNotEqualTo(expectTotalPrice) - assertThat(order.totalPrice).isEqualTo(expectTotalPrice) + // then + val expectOriginPrice = items.sumOf { + it.price * (BigDecimal.valueOf(orderQuantity)) } - ) + val expectDiscountPrice = when (coupon.type) { + Coupon.DiscountType.RATE -> expectOriginPrice * BigDecimal.valueOf(coupon.discount).divide(BigDecimal.valueOf(100)) + Coupon.DiscountType.AMOUNT -> BigDecimal.valueOf(coupon.discount) + Coupon.DiscountType.NONE -> BigDecimal.ZERO + } + val expectTotalPrice = expectOriginPrice.minus(expectDiscountPrice) + + assertThat(order.originPrice).isEqualTo(expectOriginPrice) + assertThat(order.discountPrice).isEqualTo(expectDiscountPrice) + assertThat(order.totalPrice).isEqualTo(expectTotalPrice) + } } } \ No newline at end of file