From 77a66ee02ccfbe9b92b1683e871fdf2a26169595 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 2 Oct 2026 11:33:55 +0900 Subject: [PATCH] =?UTF-8?q?fix(gift):=20=EC=A0=84=EB=8B=AC=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20=EC=A0=84=20=EC=82=AC=EC=84=9C=ED=95=A8=20=EC=A3=BC?= =?UTF-8?q?=EC=86=8C=EB=A5=BC=20=EB=85=B8=EC=B6=9C=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../v2/gift/application/GiftQueryService.kt | 2 +- .../gift/adapter/in/web/GiftControllerTest.kt | 75 +++++++----- .../gift/application/GiftQueryServiceTest.kt | 109 +++++++++++++----- 3 files changed, 131 insertions(+), 55 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/application/GiftQueryService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/application/GiftQueryService.kt index 8bd5c35b..8f9ae340 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/application/GiftQueryService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/application/GiftQueryService.kt @@ -251,7 +251,7 @@ class GiftQueryService( } private fun mailboxFor(direction: GiftDirection, status: GiftStatus): GiftMailboxResult? { - if (direction != GiftDirection.SENT || status != GiftStatus.RECEIVED) return null + if (direction != GiftDirection.SENT || status in TERMINAL_STATUSES) return null return giftMailboxRepository.findByIdOrNull(GiftMailbox.SINGLETON_ID)?.let { GiftMailboxResult( name = it.name, diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/v2/api/gift/adapter/in/web/GiftControllerTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/v2/api/gift/adapter/in/web/GiftControllerTest.kt index e159ca08..b84856da 100644 --- a/src/test/kotlin/kr/co/vividnext/sodalive/v2/api/gift/adapter/in/web/GiftControllerTest.kt +++ b/src/test/kotlin/kr/co/vividnext/sodalive/v2/api/gift/adapter/in/web/GiftControllerTest.kt @@ -194,26 +194,10 @@ class GiftControllerTest @Autowired constructor( } @Test - @DisplayName("발신자는 운송장 등록 전 선물 상세에서 받을 주소를 조회한다") - fun shouldGetMailboxForSentReceivedGiftDetail() { + @DisplayName("발신자는 전달 완료 전 정상 진행 선물 상세에서 받을 주소를 조회한다") + fun shouldGetMailboxForSentNormalProgressGiftDetailBeforeDelivered() { val sender = memberRepository.save(Member(password = "password", nickname = "fan")) val recipient = memberRepository.save(Member(password = "password", nickname = "creator")) - val gift = saveGift( - applicationNo = "G-CONTROLLER-MAILBOX", - senderMemberId = sender.id!!, - recipientMemberId = recipient.id!!, - status = GiftStatus.RECEIVED - ) - giftDeliveryRepository.save( - GiftDelivery( - giftId = gift.id!!, - senderName = "홍길동", - senderPhoneNumber = "01012345678", - senderZipCode = "06234", - senderAddress = "서울시 강남구", - trackingDeadlineAt = LocalDateTime.of(2026, 10, 2, 12, 0) - ) - ) giftMailboxRepository.save( GiftMailbox( name = "소다라이브 선물 담당자", @@ -223,16 +207,41 @@ class GiftControllerTest @Autowired constructor( addressDetail = "3층 선물 접수처" ) ) - - mockMvc.perform( - get("/api/v2/gifts/{applicationNo}", gift.applicationNo) - .with(user(MemberAdapter(sender))) + val statuses = listOf( + GiftStatus.RECEIVED, + GiftStatus.TRACKING_REGISTERED, + GiftStatus.ARRIVED_AT_MAILBOX, + GiftStatus.INSPECTION_COMPLETED ) - .andExpect(status().isOk) - .andExpect(jsonPath("$.success").value(true)) - .andExpect(jsonPath("$.data.mailbox.name").value("소다라이브 선물 담당자")) - .andExpect(jsonPath("$.data.mailbox.phoneNumber").value("01012345678")) - .andExpect(jsonPath("$.data.mailbox.address").value("(06234) 서울시 강남구, 3층 선물 접수처")) + + statuses.forEachIndexed { index, giftStatus -> + val gift = saveGift( + applicationNo = "G-C-MBOX-$index", + senderMemberId = sender.id!!, + recipientMemberId = recipient.id!!, + status = giftStatus + ) + giftDeliveryRepository.save( + GiftDelivery( + giftId = gift.id!!, + senderName = "홍길동", + senderPhoneNumber = "01012345678", + senderZipCode = "06234", + senderAddress = "서울시 강남구", + trackingDeadlineAt = LocalDateTime.of(2026, 10, 2, 12, 0) + ) + ).applyStatusTimes(giftStatus) + + mockMvc.perform( + get("/api/v2/gifts/{applicationNo}", gift.applicationNo) + .with(user(MemberAdapter(sender))) + ) + .andExpect(status().isOk) + .andExpect(jsonPath("$.success").value(true)) + .andExpect(jsonPath("$.data.mailbox.name").value("소다라이브 선물 담당자")) + .andExpect(jsonPath("$.data.mailbox.phoneNumber").value("01012345678")) + .andExpect(jsonPath("$.data.mailbox.address").value("(06234) 서울시 강남구, 3층 선물 접수처")) + } } @Test @@ -508,6 +517,18 @@ class GiftControllerTest @Autowired constructor( isActive = isActive ) + private fun GiftDelivery.applyStatusTimes(status: GiftStatus) { + if (status.ordinal >= GiftStatus.TRACKING_REGISTERED.ordinal) { + trackingRegisteredAt = LocalDateTime.of(2026, 9, 30, 12, 0) + } + if (status.ordinal >= GiftStatus.ARRIVED_AT_MAILBOX.ordinal) { + arrivedAtMailboxAt = LocalDateTime.of(2026, 10, 1, 12, 0) + } + if (status.ordinal >= GiftStatus.INSPECTION_COMPLETED.ordinal) { + inspectionCompletedAt = LocalDateTime.of(2026, 10, 2, 12, 0) + } + } + private companion object { const val SENDER_ID = 1L const val RECIPIENT_ID = 2L diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/v2/gift/application/GiftQueryServiceTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/v2/gift/application/GiftQueryServiceTest.kt index c44e8c7b..6eef5e99 100644 --- a/src/test/kotlin/kr/co/vividnext/sodalive/v2/gift/application/GiftQueryServiceTest.kt +++ b/src/test/kotlin/kr/co/vividnext/sodalive/v2/gift/application/GiftQueryServiceTest.kt @@ -234,24 +234,10 @@ class GiftQueryServiceTest @Autowired constructor( } @Test - @DisplayName("보낸 선물의 운송장 등록 전 상세만 받을 주소를 반환한다") - fun shouldReturnMailboxOnlyForSentReceivedGiftDetail() { + @DisplayName("보낸 선물의 전달 완료 전 정상 진행 상세는 받을 주소를 반환한다") + fun shouldReturnMailboxForSentNormalProgressGiftDetailBeforeDelivered() { val sender = saveMember("fan") val recipient = saveMember("creator") - val receivedGift = saveGift( - applicationNo = "G-MAILBOX-RECEIVED", - senderMemberId = sender.id!!, - recipientMemberId = recipient.id!!, - status = GiftStatus.RECEIVED - ) - saveDelivery(receivedGift) - val trackingGift = saveGift( - applicationNo = "G-MAILBOX-TRACKING", - senderMemberId = sender.id!!, - recipientMemberId = recipient.id!!, - status = GiftStatus.TRACKING_REGISTERED - ) - saveDelivery(trackingGift).trackingRegisteredAt = NOW giftMailboxRepository.save( GiftMailbox( name = "소다라이브 선물 담당자", @@ -262,20 +248,77 @@ class GiftQueryServiceTest @Autowired constructor( ) ) val service = queryService() + val allowedStatuses = listOf( + GiftStatus.RECEIVED, + GiftStatus.TRACKING_REGISTERED, + GiftStatus.ARRIVED_AT_MAILBOX, + GiftStatus.INSPECTION_COMPLETED + ) - val receivedResult = service.getGiftDetail(sender.id!!, receivedGift.applicationNo) - val trackingSenderResult = service.getGiftDetail(sender.id!!, trackingGift.applicationNo) - val trackingRecipientResult = service.getGiftDetail(recipient.id!!, trackingGift.applicationNo) + allowedStatuses.forEachIndexed { index, status -> + val gift = saveGift( + applicationNo = "G-MAILBOX-ALLOWED-$index", + senderMemberId = sender.id!!, + recipientMemberId = recipient.id!!, + status = status + ) + saveDelivery(gift).applyStatusTimes(status) - assertEquals("소다라이브 선물 담당자", receivedResult.mailbox?.name) - assertEquals("01012345678", receivedResult.mailbox?.phoneNumber) - assertEquals("(06234) 서울시 강남구, 3층 선물 접수처", receivedResult.mailbox?.address) - assertNull(trackingSenderResult.mailbox) - assertNull(trackingRecipientResult.mailbox) + val result = service.getGiftDetail(sender.id!!, gift.applicationNo) + + assertEquals("소다라이브 선물 담당자", result.mailbox?.name) + assertEquals("01012345678", result.mailbox?.phoneNumber) + assertEquals("(06234) 서울시 강남구, 3층 선물 접수처", result.mailbox?.address) + assertEquals(status == GiftStatus.RECEIVED, result.trackingRequired) + } } @Test - @DisplayName("받을 주소가 없으면 운송장 등록 전 상세도 mailbox가 null이다") + @DisplayName("보낸 선물의 종료 상태와 받은 선물 상세는 받을 주소를 반환하지 않는다") + fun shouldReturnNullMailboxForTerminalOrReceivedGiftDetail() { + val sender = saveMember("fan") + val recipient = saveMember("creator") + giftMailboxRepository.save( + GiftMailbox( + name = "소다라이브 선물 담당자", + phoneNumber = "01012345678", + zipCode = "06234", + address = "서울시 강남구", + addressDetail = "3층 선물 접수처" + ) + ) + val service = queryService() + val terminalStatuses = listOf(GiftStatus.DELIVERED, GiftStatus.UNDELIVERABLE, GiftStatus.CANCELED) + + terminalStatuses.forEachIndexed { index, status -> + val gift = saveGift( + applicationNo = "G-MAILBOX-TERMINAL-$index", + senderMemberId = sender.id!!, + recipientMemberId = recipient.id!!, + status = status + ) + saveDelivery(gift).applyStatusTimes(status) + + val result = service.getGiftDetail(sender.id!!, gift.applicationNo) + + assertNull(result.mailbox) + } + + val receivedGift = saveGift( + applicationNo = "G-MAILBOX-RECIPIENT", + senderMemberId = sender.id!!, + recipientMemberId = recipient.id!!, + status = GiftStatus.TRACKING_REGISTERED + ) + saveDelivery(receivedGift).applyStatusTimes(GiftStatus.TRACKING_REGISTERED) + + val recipientResult = service.getGiftDetail(recipient.id!!, receivedGift.applicationNo) + + assertNull(recipientResult.mailbox) + } + + @Test + @DisplayName("받을 주소가 없으면 전달 완료 전 정상 진행 상세도 mailbox가 null이다") fun shouldReturnNullMailboxWhenMailboxNotConfigured() { val sender = saveMember("fan") val recipient = saveMember("creator") @@ -283,9 +326,9 @@ class GiftQueryServiceTest @Autowired constructor( applicationNo = "G-MAILBOX-EMPTY", senderMemberId = sender.id!!, recipientMemberId = recipient.id!!, - status = GiftStatus.RECEIVED + status = GiftStatus.INSPECTION_COMPLETED ) - saveDelivery(gift) + saveDelivery(gift).applyStatusTimes(GiftStatus.INSPECTION_COMPLETED) val result = queryService().getGiftDetail(sender.id!!, gift.applicationNo) @@ -506,6 +549,18 @@ class GiftQueryServiceTest @Autowired constructor( ) ) + private fun GiftDelivery.applyStatusTimes(status: GiftStatus) { + if (status.ordinal >= GiftStatus.TRACKING_REGISTERED.ordinal) trackingRegisteredAt = NOW.plusHours(1) + if (status.ordinal >= GiftStatus.ARRIVED_AT_MAILBOX.ordinal) arrivedAtMailboxAt = NOW.plusHours(2) + if (status.ordinal >= GiftStatus.INSPECTION_COMPLETED.ordinal) inspectionCompletedAt = NOW.plusHours(3) + if (status == GiftStatus.DELIVERED) deliveredAt = NOW.plusHours(4) + if (status == GiftStatus.UNDELIVERABLE) { + undeliverableAt = NOW.plusHours(4) + undeliverableReason = "검수 실패" + } + if (status == GiftStatus.CANCELED) canceledAt = NOW.plusHours(1) + } + private fun queryService() = GiftQueryService( categoryRepository, sizePriceRepository,