From 99aa38ee6d0629d906bdbcaa0b8720ffda929679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EA=B1=B4=EC=B0=BD?= <92219795+this-is-spear@users.noreply.github.com> Date: Sun, 19 May 2024 13:57:09 +0900 Subject: [PATCH 1/8] =?UTF-8?q?feature=20:=20GiftCouponMessageController?= =?UTF-8?q?=20=EC=84=A0=EB=AC=BC=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=A0=84?= =?UTF-8?q?=EC=86=A1=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20=EB=B0=8F?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../port/in/GiftCouponByMessageUseCase.kt | 7 ++++ .../in/web/GiftCouponMessageController.kt | 25 ++++++++++++ .../port/in/web/dto/GiftMessageResponse.kt | 9 +++++ .../coupon/domain/coupon/GiftMessage.kt | 14 +++++++ .../in/web/GiftCouponMessageControllerTest.kt | 40 +++++++++++++++++++ 5 files changed, 95 insertions(+) create mode 100644 coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/GiftCouponByMessageUseCase.kt create mode 100644 coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/dto/GiftMessageResponse.kt create mode 100644 coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftMessage.kt diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/GiftCouponByMessageUseCase.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/GiftCouponByMessageUseCase.kt new file mode 100644 index 0000000..6c5a6fe --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/GiftCouponByMessageUseCase.kt @@ -0,0 +1,7 @@ +package com.example.estdelivery.coupon.application.port.`in` + +import com.example.estdelivery.coupon.domain.coupon.GiftMessage + +interface GiftCouponByMessageUseCase { + fun sendGiftAvailableCoupon(memberId: Long, couponId: Long, giftMessage: String): GiftMessage +} diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt index aa9a72c..d9ea35f 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt @@ -1,19 +1,26 @@ package com.example.estdelivery.coupon.application.port.`in`.web import com.example.estdelivery.coupon.application.port.`in`.FindAvailableGiftCouponUseCase +import com.example.estdelivery.coupon.application.port.`in`.GiftCouponByMessageUseCase import com.example.estdelivery.coupon.application.port.`in`.web.dto.GiftCouponResponse import com.example.estdelivery.coupon.application.port.`in`.web.dto.GiftCouponResponses +import com.example.estdelivery.coupon.application.port.`in`.web.dto.GiftMessageResponse import com.example.estdelivery.coupon.domain.coupon.Coupon.FixDiscountCoupon import com.example.estdelivery.coupon.domain.coupon.Coupon.RateDiscountCoupon +import java.net.URL import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestHeader import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping("/gift-coupons") class GiftCouponMessageController( private val findAvailableGiftCouponUseCase: FindAvailableGiftCouponUseCase, + private val giftCouponByMessageUseCase: GiftCouponByMessageUseCase, ) { @GetMapping fun findAvailableGiftCoupons(@RequestHeader(value = "Member-ID") memberId: Long): GiftCouponResponses = @@ -29,4 +36,22 @@ class GiftCouponMessageController( }.let { GiftCouponResponses(it) } + + @PostMapping("/send/{couponId}") + fun sendGiftAvailableCoupon( + @RequestHeader(value = "Member-ID") memberId: Long, + @RequestParam message: String, + @PathVariable couponId: Long, + ): GiftMessageResponse = + giftCouponByMessageUseCase.sendGiftAvailableCoupon( + memberId, + couponId, + message, + ).let { + GiftMessageResponse( + senderName = it.sender.name, + description = it.giftMessage, + enrollHref = URL("http", "localhost", 8080, "/gift-coupons/enroll/${it.giftCode}") + ) + } } diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/dto/GiftMessageResponse.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/dto/GiftMessageResponse.kt new file mode 100644 index 0000000..c6ad5c8 --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/dto/GiftMessageResponse.kt @@ -0,0 +1,9 @@ +package com.example.estdelivery.coupon.application.port.`in`.web.dto + +import java.net.URL + +data class GiftMessageResponse( + val senderName: String, + val description: String, + val enrollHref: URL, +) diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftMessage.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftMessage.kt new file mode 100644 index 0000000..df02e29 --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftMessage.kt @@ -0,0 +1,14 @@ +package com.example.estdelivery.coupon.domain.coupon + +import com.example.estdelivery.coupon.domain.member.Member + +data class GiftMessage( + val sender: Member, + val giftMessage: String, + val giftCode: String, + val giftCoupon: GiftCoupon +) { + init { + require(giftCode.isNotBlank()) { "선물 코드는 필수입니다." } + } +} diff --git a/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageControllerTest.kt b/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageControllerTest.kt index 3fd4b46..c4c956e 100644 --- a/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageControllerTest.kt +++ b/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageControllerTest.kt @@ -1,8 +1,11 @@ package com.example.estdelivery.coupon.application.port.`in`.web import com.example.estdelivery.coupon.application.port.`in`.FindAvailableGiftCouponUseCase +import com.example.estdelivery.coupon.application.port.`in`.GiftCouponByMessageUseCase import com.example.estdelivery.coupon.domain.coupon.GiftCoupon +import com.example.estdelivery.coupon.domain.coupon.GiftMessage import com.example.estdelivery.coupon.domain.fixture.나눠준_비율_할인_쿠폰 +import com.example.estdelivery.coupon.domain.fixture.일건창 import com.ninjasquad.springmockk.MockkBean import io.mockk.every import org.junit.jupiter.api.Test @@ -11,6 +14,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.get +import org.springframework.test.web.servlet.post private const val MEMBER_ID = "Member-ID" @@ -20,6 +24,9 @@ class GiftCouponMessageControllerTest { @MockkBean lateinit var findAvailableGiftCouponUseCase: FindAvailableGiftCouponUseCase + @MockkBean + lateinit var giftCouponByMessageUseCase: GiftCouponByMessageUseCase + @Autowired lateinit var mockMvc: MockMvc @@ -44,4 +51,37 @@ class GiftCouponMessageControllerTest { } } } + + @Test + fun `쿠폰 선물할 메시지를 전달받는다`() { + // given + val 일건창 = 일건창() + val 선물할_쿠폰 = GiftCoupon(나눠준_비율_할인_쿠폰) + + // when + val messageDescription = "선물 메시지" + val giftCode = "A1B2C3D4" + + every { + giftCouponByMessageUseCase.sendGiftAvailableCoupon(일건창.id, 선물할_쿠폰.coupon.id!!, messageDescription) + } returns GiftMessage( + sender = 일건창, + giftMessage = messageDescription, + giftCoupon = 선물할_쿠폰, + giftCode = giftCode + ) + + // then + mockMvc.post("/gift-coupons/send/${선물할_쿠폰.coupon.id}") { + header(MEMBER_ID, 일건창.id) + param("message", messageDescription) + }.andExpect { + status { isOk() } + content { + jsonPath("$.enrollHref") { value("http://localhost:8080/gift-coupons/enroll/$giftCode") } + jsonPath("$.senderName") { value(일건창.name) } + jsonPath("$.description") { value(messageDescription) } + } + } + } } From 37faa61c27ba597e54dedb3c2ed852b0e800711e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EA=B1=B4=EC=B0=BD?= <92219795+this-is-spear@users.noreply.github.com> Date: Sun, 19 May 2024 14:17:00 +0900 Subject: [PATCH 2/8] =?UTF-8?q?feature=20:=20GiftCouponCode=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../port/in/web/GiftCouponMessageController.kt | 2 +- .../coupon/domain/coupon/GiftCouponCode.kt | 9 +++++++++ .../coupon/domain/coupon/GiftMessage.kt | 8 ++------ .../in/web/GiftCouponMessageControllerTest.kt | 3 ++- .../coupon/domain/coupon/GiftCouponCodeTest.kt | 15 +++++++++++++++ 5 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCode.kt create mode 100644 coupon/src/test/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCodeTest.kt diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt index d9ea35f..0a4343c 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt @@ -51,7 +51,7 @@ class GiftCouponMessageController( GiftMessageResponse( senderName = it.sender.name, description = it.giftMessage, - enrollHref = URL("http", "localhost", 8080, "/gift-coupons/enroll/${it.giftCode}") + enrollHref = URL("http", "localhost", 8080, "/gift-coupons/enroll/${it.giftCouponCode}") ) } } diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCode.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCode.kt new file mode 100644 index 0000000..b7dd0db --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCode.kt @@ -0,0 +1,9 @@ +package com.example.estdelivery.coupon.domain.coupon + +data class GiftCouponCode( + val code: String, +) { + init { + require(code.isNotBlank()) { "쿠폰 선물 코드는 비어있을 수 없습니다." } + } +} diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftMessage.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftMessage.kt index df02e29..db8318f 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftMessage.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftMessage.kt @@ -5,10 +5,6 @@ import com.example.estdelivery.coupon.domain.member.Member data class GiftMessage( val sender: Member, val giftMessage: String, - val giftCode: String, + val giftCouponCode: GiftCouponCode, val giftCoupon: GiftCoupon -) { - init { - require(giftCode.isNotBlank()) { "선물 코드는 필수입니다." } - } -} +) diff --git a/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageControllerTest.kt b/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageControllerTest.kt index c4c956e..3effe01 100644 --- a/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageControllerTest.kt +++ b/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageControllerTest.kt @@ -3,6 +3,7 @@ package com.example.estdelivery.coupon.application.port.`in`.web import com.example.estdelivery.coupon.application.port.`in`.FindAvailableGiftCouponUseCase import com.example.estdelivery.coupon.application.port.`in`.GiftCouponByMessageUseCase import com.example.estdelivery.coupon.domain.coupon.GiftCoupon +import com.example.estdelivery.coupon.domain.coupon.GiftCouponCode import com.example.estdelivery.coupon.domain.coupon.GiftMessage import com.example.estdelivery.coupon.domain.fixture.나눠준_비율_할인_쿠폰 import com.example.estdelivery.coupon.domain.fixture.일건창 @@ -68,7 +69,7 @@ class GiftCouponMessageControllerTest { sender = 일건창, giftMessage = messageDescription, giftCoupon = 선물할_쿠폰, - giftCode = giftCode + giftCouponCode = GiftCouponCode(giftCode) ) // then diff --git a/coupon/src/test/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCodeTest.kt b/coupon/src/test/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCodeTest.kt new file mode 100644 index 0000000..005bd54 --- /dev/null +++ b/coupon/src/test/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCodeTest.kt @@ -0,0 +1,15 @@ +package com.example.estdelivery.coupon.domain.coupon + +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.FreeSpec +import io.kotest.matchers.shouldBe + +class GiftCouponCodeTest : FreeSpec({ + "쿠폰 선물 코드는 비어있을 수 없다." { + val code = "" + val exception = shouldThrow { + GiftCouponCode(code) + } + exception.message shouldBe "쿠폰 선물 코드는 비어있을 수 없습니다." + } +}) From 3df5e588a9ac713a7dcaf6f208b6e4515b888fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EA=B1=B4=EC=B0=BD?= <92219795+this-is-spear@users.noreply.github.com> Date: Sun, 19 May 2024 14:30:04 +0900 Subject: [PATCH 3/8] =?UTF-8?q?feature=20:=20GiftCouponByMessageService=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/GiftCouponByMessageService.kt | 35 +++++++++++ .../coupon/application/ServiceBeanManager.kt | 20 +++++- .../out/CreateGiftCouponMessageStatePort.kt | 9 +++ .../persistence/GiftCouponMessageAdapter.kt | 14 +++++ .../GiftCouponByMessageServiceTest.kt | 62 +++++++++++++++++++ 5 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt create mode 100644 coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/CreateGiftCouponMessageStatePort.kt create mode 100644 coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/GiftCouponMessageAdapter.kt create mode 100644 coupon/src/test/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageServiceTest.kt diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt new file mode 100644 index 0000000..2663de9 --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt @@ -0,0 +1,35 @@ +package com.example.estdelivery.coupon.application + +import com.example.estdelivery.coupon.application.port.`in`.GiftCouponByMessageUseCase +import com.example.estdelivery.coupon.application.port.out.CreateGiftCouponMessageStatePort +import com.example.estdelivery.coupon.application.port.out.LoadMemberStatePort +import com.example.estdelivery.coupon.application.port.out.UpdateMemberStatePort +import com.example.estdelivery.coupon.application.utils.TransactionArea +import com.example.estdelivery.coupon.domain.coupon.Coupon +import com.example.estdelivery.coupon.domain.coupon.GiftMessage +import com.example.estdelivery.coupon.domain.member.Member + +class GiftCouponByMessageService( + loadMemberStatePort: LoadMemberStatePort, + createGiftCouponMessageStatePort: CreateGiftCouponMessageStatePort, + updateMemberStatePort: UpdateMemberStatePort, + private val transactionArea: TransactionArea, + private val findMember: (Long) -> Member = { loadMemberStatePort.findMember(it) }, + private val createGiftMessage: (Member, Coupon, String) -> GiftMessage = { sender, coupon, message -> + createGiftCouponMessageStatePort.create(sender, coupon, message) + }, + private val updateMembersCoupon: (Member) -> Unit = { updateMemberStatePort.updateMembersCoupon(it) } +) : GiftCouponByMessageUseCase { + override fun sendGiftAvailableCoupon(memberId: Long, couponId: Long, giftMessage: String): GiftMessage { + return transactionArea.run { + val sender = findMember(memberId) + val coupon = sender.showMyCouponBook().find { it.id == couponId } + if (coupon == null) { + throw IllegalArgumentException("쿠폰이 존재하지 않습니다.") + } + sender.useCoupon(coupon) + updateMembersCoupon(sender) + createGiftMessage(sender, coupon, giftMessage) + } + } +} diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/ServiceBeanManager.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/ServiceBeanManager.kt index 368a444..155dc82 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/ServiceBeanManager.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/ServiceBeanManager.kt @@ -1,12 +1,30 @@ package com.example.estdelivery.coupon.application +import com.example.estdelivery.coupon.application.port.`in`.FindAvailableGiftCouponUseCase +import com.example.estdelivery.coupon.application.port.`in`.GiftCouponByMessageUseCase +import com.example.estdelivery.coupon.application.port.out.CreateGiftCouponMessageStatePort import com.example.estdelivery.coupon.application.port.out.LoadMemberStatePort +import com.example.estdelivery.coupon.application.port.out.UpdateMemberStatePort +import com.example.estdelivery.coupon.application.utils.TransactionArea import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration class ServiceBeanManager { @Bean - fun findAvailableGiftCouponService(loadMemberStatePort: LoadMemberStatePort) = + fun findAvailableGiftCouponUseCase(loadMemberStatePort: LoadMemberStatePort): FindAvailableGiftCouponUseCase = FindAvailableGiftCouponService(loadMemberStatePort) + + @Bean + fun giftCouponByMessageUseCase( + transactionArea: TransactionArea, + loadMemberStatePort: LoadMemberStatePort, + createGiftCouponMessageStatePort: CreateGiftCouponMessageStatePort, + updateMemberStatePort: UpdateMemberStatePort, + ): GiftCouponByMessageUseCase = GiftCouponByMessageService( + loadMemberStatePort, + createGiftCouponMessageStatePort, + updateMemberStatePort, + transactionArea, + ) } diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/CreateGiftCouponMessageStatePort.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/CreateGiftCouponMessageStatePort.kt new file mode 100644 index 0000000..03ebac5 --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/CreateGiftCouponMessageStatePort.kt @@ -0,0 +1,9 @@ +package com.example.estdelivery.coupon.application.port.out + +import com.example.estdelivery.coupon.domain.coupon.Coupon +import com.example.estdelivery.coupon.domain.coupon.GiftMessage +import com.example.estdelivery.coupon.domain.member.Member + +interface CreateGiftCouponMessageStatePort { + fun create(sender: Member, coupon: Coupon, message: String): GiftMessage +} diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/GiftCouponMessageAdapter.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/GiftCouponMessageAdapter.kt new file mode 100644 index 0000000..5720fa2 --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/GiftCouponMessageAdapter.kt @@ -0,0 +1,14 @@ +package com.example.estdelivery.coupon.application.port.out.adapter.persistence + +import com.example.estdelivery.coupon.application.port.out.CreateGiftCouponMessageStatePort +import com.example.estdelivery.coupon.domain.coupon.Coupon +import com.example.estdelivery.coupon.domain.coupon.GiftMessage +import com.example.estdelivery.coupon.domain.member.Member +import org.springframework.stereotype.Component + +@Component +class GiftCouponMessageAdapter : CreateGiftCouponMessageStatePort { + override fun create(sender: Member, coupon: Coupon, message: String): GiftMessage { + TODO("Not yet implemented") + } +} diff --git a/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageServiceTest.kt b/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageServiceTest.kt new file mode 100644 index 0000000..e47b7ad --- /dev/null +++ b/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageServiceTest.kt @@ -0,0 +1,62 @@ +package com.example.estdelivery.coupon.application + +import com.example.estdelivery.coupon.application.port.out.CreateGiftCouponMessageStatePort +import com.example.estdelivery.coupon.application.port.out.LoadMemberStatePort +import com.example.estdelivery.coupon.application.port.out.UpdateMemberStatePort +import com.example.estdelivery.coupon.application.utils.TransactionArea +import com.example.estdelivery.coupon.domain.coupon.GiftCoupon +import com.example.estdelivery.coupon.domain.coupon.GiftCouponCode +import com.example.estdelivery.coupon.domain.coupon.GiftMessage +import com.example.estdelivery.coupon.domain.fixture.나눠준_비율_할인_쿠폰 +import com.example.estdelivery.coupon.domain.fixture.일건창 +import com.example.estdelivery.coupon.domain.member.Member +import io.kotest.core.spec.style.FreeSpec +import io.kotest.matchers.shouldBe +import io.mockk.every +import io.mockk.mockk +import io.mockk.slot + +class GiftCouponByMessageServiceTest : FreeSpec({ + val loadMemberStatePort = mockk() + val createGiftCouponMessageStatePort = mockk() + val updateMemberStatePort = mockk() + lateinit var giftCouponByMessageService: GiftCouponByMessageService + + beforeTest { + giftCouponByMessageService = GiftCouponByMessageService( + loadMemberStatePort, + createGiftCouponMessageStatePort, + updateMemberStatePort, + TransactionArea() + ) + } + + "쿠폰 선물하기 위한 메시지를 전달받는다." { + // given + val 선물할_쿠폰 = 나눠준_비율_할인_쿠폰 + val 일건창 = 일건창().apply { + receiveCoupon(선물할_쿠폰) + } + val 변경된_회원_정보 = slot() + val 쿠폰_코드 = "ABC123" + val 선물_메시지 = "선물 메시지" + + // when + every { loadMemberStatePort.findMember(일건창.id) } returns 일건창 + every { createGiftCouponMessageStatePort.create(일건창, 선물할_쿠폰, 선물_메시지) } returns GiftMessage( + 일건창, + 선물_메시지, + GiftCouponCode(쿠폰_코드), + GiftCoupon(선물할_쿠폰) + ) + every { updateMemberStatePort.updateMembersCoupon(capture(변경된_회원_정보)) } answers { nothing } + + val giftAvailableCoupon = + giftCouponByMessageService.sendGiftAvailableCoupon(일건창.id, 선물할_쿠폰.id!!, 선물_메시지) + + // then + 변경된_회원_정보.captured.showMyCouponBook().find { it.id == 선물할_쿠폰.id } shouldBe null + giftAvailableCoupon.sender.id shouldBe 일건창.id + giftAvailableCoupon.giftCouponCode.code shouldBe 쿠폰_코드 + } +}) From 7b569c5b3e3b2faff8a04514331d7e5512e878b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EA=B1=B4=EC=B0=BD?= <92219795+this-is-spear@users.noreply.github.com> Date: Sun, 19 May 2024 14:39:39 +0900 Subject: [PATCH 4/8] =?UTF-8?q?refactor=20:=20repository=20=EB=A6=B0?= =?UTF-8?q?=ED=8A=B8=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/adapter/persistence/repository/CouponRepository.kt | 3 +-- .../port/out/adapter/persistence/repository/ShopRepository.kt | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/CouponRepository.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/CouponRepository.kt index f36b57c..cc33044 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/CouponRepository.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/CouponRepository.kt @@ -3,5 +3,4 @@ package com.example.estdelivery.coupon.application.port.out.adapter.persistence. import com.example.estdelivery.coupon.application.port.out.adapter.persistence.entity.CouponEntity import org.springframework.data.jpa.repository.JpaRepository -interface CouponRepository : - JpaRepository +interface CouponRepository : JpaRepository diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/ShopRepository.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/ShopRepository.kt index 2c0616e..c3732a3 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/ShopRepository.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/ShopRepository.kt @@ -3,5 +3,4 @@ package com.example.estdelivery.coupon.application.port.out.adapter.persistence. import com.example.estdelivery.coupon.application.port.out.adapter.persistence.entity.ShopEntity import org.springframework.data.jpa.repository.JpaRepository -interface ShopRepository : - JpaRepository +interface ShopRepository : JpaRepository From 1be49bc44b262e8b85e4a0004a47159ac29de108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EA=B1=B4=EC=B0=BD?= <92219795+this-is-spear@users.noreply.github.com> Date: Sun, 19 May 2024 14:48:48 +0900 Subject: [PATCH 5/8] =?UTF-8?q?test=20:=20=EC=8B=A4=ED=8C=A8=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/port/in/web/GiftCouponMessageController.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt index 0a4343c..9cc5bb9 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt @@ -51,7 +51,7 @@ class GiftCouponMessageController( GiftMessageResponse( senderName = it.sender.name, description = it.giftMessage, - enrollHref = URL("http", "localhost", 8080, "/gift-coupons/enroll/${it.giftCouponCode}") + enrollHref = URL("http", "localhost", 8080, "/gift-coupons/enroll/${it.giftCouponCode.code}") ) } } From fbdf0dc8c90c9c114af6e3d95020c13dd0507055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EA=B1=B4=EC=B0=BD?= <92219795+this-is-spear@users.noreply.github.com> Date: Sun, 19 May 2024 14:53:23 +0900 Subject: [PATCH 6/8] =?UTF-8?q?refactor=20:=20GiftCouponByMessageService?= =?UTF-8?q?=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coupon/application/GiftCouponByMessageService.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt index 2663de9..c20ad61 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt @@ -20,6 +20,18 @@ class GiftCouponByMessageService( }, private val updateMembersCoupon: (Member) -> Unit = { updateMemberStatePort.updateMembersCoupon(it) } ) : GiftCouponByMessageUseCase { + /** + * 선물 메시지를 통해 쿠폰을 선물한다. + * + * 1. 보낼 사람의 정보를 조회한다. + * 2. 보낼 쿠폰의 정보를 조회한다. + * 3. 보낼 사람의 쿠폰북에서 쿠폰을 삭제한다. + * 4. 선물 메시지를 생성한다. + * + * @param memberId 선물하는 회원 식별자 + * @param couponId 선물할 쿠폰 식별자 + * @param giftMessage 선물 메시지 + */ override fun sendGiftAvailableCoupon(memberId: Long, couponId: Long, giftMessage: String): GiftMessage { return transactionArea.run { val sender = findMember(memberId) From 5cf7ecf88eadca468e84f8f8ce8cb519f9069dcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EA=B1=B4=EC=B0=BD?= <92219795+this-is-spear@users.noreply.github.com> Date: Sun, 19 May 2024 20:15:05 +0900 Subject: [PATCH 7/8] =?UTF-8?q?refactor=20:=20ValidateGiftCouponCodeStateP?= =?UTF-8?q?ort=20=EB=A5=BC=20=EC=9D=B4=EC=9A=A9=ED=95=9C=20=EC=BF=A0?= =?UTF-8?q?=ED=8F=B0=20=EC=BD=94=EB=93=9C=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/GiftCouponByMessageService.kt | 22 +++++++++++++++---- .../coupon/application/ServiceBeanManager.kt | 3 +++ .../out/CreateGiftCouponMessageStatePort.kt | 3 ++- .../out/ValidateGiftCouponCodeStatePort.kt | 7 ++++++ .../coupon/domain/coupon/GiftCouponCode.kt | 8 +++++++ .../GiftCouponByMessageServiceTest.kt | 18 +++++++++------ 6 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/ValidateGiftCouponCodeStatePort.kt diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt index c20ad61..d4eb806 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt @@ -4,8 +4,10 @@ import com.example.estdelivery.coupon.application.port.`in`.GiftCouponByMessageU import com.example.estdelivery.coupon.application.port.out.CreateGiftCouponMessageStatePort import com.example.estdelivery.coupon.application.port.out.LoadMemberStatePort import com.example.estdelivery.coupon.application.port.out.UpdateMemberStatePort +import com.example.estdelivery.coupon.application.port.out.ValidateGiftCouponCodeStatePort import com.example.estdelivery.coupon.application.utils.TransactionArea import com.example.estdelivery.coupon.domain.coupon.Coupon +import com.example.estdelivery.coupon.domain.coupon.GiftCouponCode import com.example.estdelivery.coupon.domain.coupon.GiftMessage import com.example.estdelivery.coupon.domain.member.Member @@ -13,11 +15,13 @@ class GiftCouponByMessageService( loadMemberStatePort: LoadMemberStatePort, createGiftCouponMessageStatePort: CreateGiftCouponMessageStatePort, updateMemberStatePort: UpdateMemberStatePort, + validateGiftCouponCodeStatePort: ValidateGiftCouponCodeStatePort, private val transactionArea: TransactionArea, private val findMember: (Long) -> Member = { loadMemberStatePort.findMember(it) }, - private val createGiftMessage: (Member, Coupon, String) -> GiftMessage = { sender, coupon, message -> - createGiftCouponMessageStatePort.create(sender, coupon, message) + private val createGiftMessage: (Member, Coupon, String, GiftCouponCode) -> GiftMessage = { sender, coupon, message, code -> + createGiftCouponMessageStatePort.create(sender, coupon, message, code) }, + private val validateCouponCode: (GiftCouponCode) -> Boolean = { validateGiftCouponCodeStatePort.validate(it) }, private val updateMembersCoupon: (Member) -> Unit = { updateMemberStatePort.updateMembersCoupon(it) } ) : GiftCouponByMessageUseCase { /** @@ -26,7 +30,8 @@ class GiftCouponByMessageService( * 1. 보낼 사람의 정보를 조회한다. * 2. 보낼 쿠폰의 정보를 조회한다. * 3. 보낼 사람의 쿠폰북에서 쿠폰을 삭제한다. - * 4. 선물 메시지를 생성한다. + * 4. 등록할 쿠폰 코드를 검증한다. + * 5. 선물 메시지를 생성한다. * * @param memberId 선물하는 회원 식별자 * @param couponId 선물할 쿠폰 식별자 @@ -39,9 +44,18 @@ class GiftCouponByMessageService( if (coupon == null) { throw IllegalArgumentException("쿠폰이 존재하지 않습니다.") } + val couponCode: GiftCouponCode = getGiftCouponCode() sender.useCoupon(coupon) updateMembersCoupon(sender) - createGiftMessage(sender, coupon, giftMessage) + createGiftMessage(sender, coupon, giftMessage, couponCode) } } + + private fun getGiftCouponCode(): GiftCouponCode { + lateinit var couponCode: GiftCouponCode + do { + couponCode = GiftCouponCode.create() + } while (!validateCouponCode(couponCode)) + return couponCode + } } diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/ServiceBeanManager.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/ServiceBeanManager.kt index 155dc82..8c15b5b 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/ServiceBeanManager.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/ServiceBeanManager.kt @@ -5,6 +5,7 @@ import com.example.estdelivery.coupon.application.port.`in`.GiftCouponByMessageU import com.example.estdelivery.coupon.application.port.out.CreateGiftCouponMessageStatePort import com.example.estdelivery.coupon.application.port.out.LoadMemberStatePort import com.example.estdelivery.coupon.application.port.out.UpdateMemberStatePort +import com.example.estdelivery.coupon.application.port.out.ValidateGiftCouponCodeStatePort import com.example.estdelivery.coupon.application.utils.TransactionArea import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @@ -20,11 +21,13 @@ class ServiceBeanManager { transactionArea: TransactionArea, loadMemberStatePort: LoadMemberStatePort, createGiftCouponMessageStatePort: CreateGiftCouponMessageStatePort, + validateGiftCouponCodeStatePort: ValidateGiftCouponCodeStatePort, updateMemberStatePort: UpdateMemberStatePort, ): GiftCouponByMessageUseCase = GiftCouponByMessageService( loadMemberStatePort, createGiftCouponMessageStatePort, updateMemberStatePort, + validateGiftCouponCodeStatePort, transactionArea, ) } diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/CreateGiftCouponMessageStatePort.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/CreateGiftCouponMessageStatePort.kt index 03ebac5..89eee5d 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/CreateGiftCouponMessageStatePort.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/CreateGiftCouponMessageStatePort.kt @@ -1,9 +1,10 @@ package com.example.estdelivery.coupon.application.port.out import com.example.estdelivery.coupon.domain.coupon.Coupon +import com.example.estdelivery.coupon.domain.coupon.GiftCouponCode import com.example.estdelivery.coupon.domain.coupon.GiftMessage import com.example.estdelivery.coupon.domain.member.Member interface CreateGiftCouponMessageStatePort { - fun create(sender: Member, coupon: Coupon, message: String): GiftMessage + fun create(sender: Member, coupon: Coupon, message: String, giftCouponCode: GiftCouponCode): GiftMessage } diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/ValidateGiftCouponCodeStatePort.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/ValidateGiftCouponCodeStatePort.kt new file mode 100644 index 0000000..c4ded8e --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/ValidateGiftCouponCodeStatePort.kt @@ -0,0 +1,7 @@ +package com.example.estdelivery.coupon.application.port.out + +import com.example.estdelivery.coupon.domain.coupon.GiftCouponCode + +interface ValidateGiftCouponCodeStatePort { + fun validate(giftCouponCode: GiftCouponCode): Boolean +} \ No newline at end of file diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCode.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCode.kt index b7dd0db..19ebcf5 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCode.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCode.kt @@ -1,9 +1,17 @@ package com.example.estdelivery.coupon.domain.coupon +import java.util.UUID + data class GiftCouponCode( val code: String, ) { init { require(code.isNotBlank()) { "쿠폰 선물 코드는 비어있을 수 없습니다." } } + + companion object { + fun create(): GiftCouponCode { + return GiftCouponCode(UUID.randomUUID().toString().replace("-", "").substring(0..9)) + } + } } diff --git a/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageServiceTest.kt b/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageServiceTest.kt index e47b7ad..4d008cc 100644 --- a/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageServiceTest.kt +++ b/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageServiceTest.kt @@ -3,6 +3,7 @@ package com.example.estdelivery.coupon.application import com.example.estdelivery.coupon.application.port.out.CreateGiftCouponMessageStatePort import com.example.estdelivery.coupon.application.port.out.LoadMemberStatePort import com.example.estdelivery.coupon.application.port.out.UpdateMemberStatePort +import com.example.estdelivery.coupon.application.port.out.ValidateGiftCouponCodeStatePort import com.example.estdelivery.coupon.application.utils.TransactionArea import com.example.estdelivery.coupon.domain.coupon.GiftCoupon import com.example.estdelivery.coupon.domain.coupon.GiftCouponCode @@ -20,13 +21,15 @@ class GiftCouponByMessageServiceTest : FreeSpec({ val loadMemberStatePort = mockk() val createGiftCouponMessageStatePort = mockk() val updateMemberStatePort = mockk() - lateinit var giftCouponByMessageService: GiftCouponByMessageService + val validateGiftCouponCodeStatePort = mockk() + lateinit var giftCouponByMessageService: GiftCouponByMessageService beforeTest { giftCouponByMessageService = GiftCouponByMessageService( loadMemberStatePort, createGiftCouponMessageStatePort, updateMemberStatePort, + validateGiftCouponCodeStatePort, TransactionArea() ) } @@ -38,25 +41,26 @@ class GiftCouponByMessageServiceTest : FreeSpec({ receiveCoupon(선물할_쿠폰) } val 변경된_회원_정보 = slot() - val 쿠폰_코드 = "ABC123" val 선물_메시지 = "선물 메시지" + val 쿠폰_코드 = GiftCouponCode.create() // when every { loadMemberStatePort.findMember(일건창.id) } returns 일건창 - every { createGiftCouponMessageStatePort.create(일건창, 선물할_쿠폰, 선물_메시지) } returns GiftMessage( + every { createGiftCouponMessageStatePort.create(일건창, 선물할_쿠폰, 선물_메시지, any()) } returns GiftMessage( 일건창, 선물_메시지, - GiftCouponCode(쿠폰_코드), + 쿠폰_코드, GiftCoupon(선물할_쿠폰) ) - every { updateMemberStatePort.updateMembersCoupon(capture(변경된_회원_정보)) } answers { nothing } + every { validateGiftCouponCodeStatePort.validate(any()) } returns true + every { updateMemberStatePort.updateMembersCoupon(capture(변경된_회원_정보)) } returns Unit val giftAvailableCoupon = giftCouponByMessageService.sendGiftAvailableCoupon(일건창.id, 선물할_쿠폰.id!!, 선물_메시지) // then 변경된_회원_정보.captured.showMyCouponBook().find { it.id == 선물할_쿠폰.id } shouldBe null - giftAvailableCoupon.sender.id shouldBe 일건창.id - giftAvailableCoupon.giftCouponCode.code shouldBe 쿠폰_코드 + giftAvailableCoupon.sender shouldBe 일건창 + giftAvailableCoupon.giftCouponCode shouldBe 쿠폰_코드 } }) From 11ee6c1c699193a13785dc5a58b8f860a2e53ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EA=B1=B4=EC=B0=BD?= <92219795+this-is-spear@users.noreply.github.com> Date: Sun, 19 May 2024 20:15:21 +0900 Subject: [PATCH 8/8] =?UTF-8?q?refactor=20:=20GiftCouponMessageAdapter=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../persistence/GiftCouponMessageAdapter.kt | 31 ++++++++++++-- .../persistence/entity/GiftMessageEntity.kt | 41 +++++++++++++++++++ .../repository/GiftMessageRepository.kt | 8 ++++ 3 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/entity/GiftMessageEntity.kt create mode 100644 coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/GiftMessageRepository.kt diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/GiftCouponMessageAdapter.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/GiftCouponMessageAdapter.kt index 5720fa2..5e142e1 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/GiftCouponMessageAdapter.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/GiftCouponMessageAdapter.kt @@ -1,14 +1,39 @@ package com.example.estdelivery.coupon.application.port.out.adapter.persistence import com.example.estdelivery.coupon.application.port.out.CreateGiftCouponMessageStatePort +import com.example.estdelivery.coupon.application.port.out.ValidateGiftCouponCodeStatePort +import com.example.estdelivery.coupon.application.port.out.adapter.persistence.entity.GiftMessageEntity +import com.example.estdelivery.coupon.application.port.out.adapter.persistence.mapper.fromCoupon +import com.example.estdelivery.coupon.application.port.out.adapter.persistence.repository.GiftMessageRepository import com.example.estdelivery.coupon.domain.coupon.Coupon +import com.example.estdelivery.coupon.domain.coupon.GiftCoupon +import com.example.estdelivery.coupon.domain.coupon.GiftCouponCode import com.example.estdelivery.coupon.domain.coupon.GiftMessage import com.example.estdelivery.coupon.domain.member.Member import org.springframework.stereotype.Component @Component -class GiftCouponMessageAdapter : CreateGiftCouponMessageStatePort { - override fun create(sender: Member, coupon: Coupon, message: String): GiftMessage { - TODO("Not yet implemented") +class GiftCouponMessageAdapter( + private val giftMessageRepository: GiftMessageRepository, +) : CreateGiftCouponMessageStatePort, ValidateGiftCouponCodeStatePort { + override fun create(sender: Member, coupon: Coupon, message: String, giftCouponCode: GiftCouponCode): GiftMessage { + val giftMessageEntity = giftMessageRepository.save( + GiftMessageEntity( + sender = sender.id, + coupon = fromCoupon(coupon), + message = message, + enrollCode = giftCouponCode.code + ) + ) + return GiftMessage( + sender = sender, + giftMessage = giftMessageEntity.message, + giftCouponCode = GiftCouponCode(giftMessageEntity.enrollCode), + giftCoupon = GiftCoupon(coupon) + ) + } + + override fun validate(giftCouponCode: GiftCouponCode): Boolean { + return giftMessageRepository.existsByEnrollCode(giftCouponCode.code) } } diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/entity/GiftMessageEntity.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/entity/GiftMessageEntity.kt new file mode 100644 index 0000000..d292050 --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/entity/GiftMessageEntity.kt @@ -0,0 +1,41 @@ +package com.example.estdelivery.coupon.application.port.out.adapter.persistence.entity + +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.JoinColumn +import jakarta.persistence.OneToOne +import jakarta.persistence.Table +import java.time.LocalDate + +@Entity +@Table(name = "gift_message") +class GiftMessageEntity( + val message: String, + @Column(name = "sender_id") + val sender: Long, + val enrollCode: String, + @OneToOne + @JoinColumn(name = "coupon_id") + val coupon: CouponEntity, + val enrollDate: LocalDate = LocalDate.now(), + val isUsed: Boolean = false, + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long? = null, +) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is GiftMessageEntity) return false + + if (id != other.id) return false + + return true + } + + override fun hashCode(): Int { + return id?.hashCode() ?: 0 + } +} diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/GiftMessageRepository.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/GiftMessageRepository.kt new file mode 100644 index 0000000..0952908 --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/GiftMessageRepository.kt @@ -0,0 +1,8 @@ +package com.example.estdelivery.coupon.application.port.out.adapter.persistence.repository + +import com.example.estdelivery.coupon.application.port.out.adapter.persistence.entity.GiftMessageEntity +import org.springframework.data.jpa.repository.JpaRepository + +interface GiftMessageRepository : JpaRepository { + fun existsByEnrollCode(enrollCode: String): Boolean +}