feat(gift): 선물함 리스트 배송지 상태를 응답한다
This commit is contained in:
@@ -62,6 +62,9 @@ data class GiftListResponse(
|
||||
counterpartMemberId = it.counterpartMemberId,
|
||||
counterpartNickname = it.counterpartNickname,
|
||||
counterpartProfileImageUrl = it.counterpartProfileImageUrl,
|
||||
recipientAddressRegistered = it.recipientAddressRegistered,
|
||||
recipientAddressDeadlineAt = it.recipientAddressDeadlineAt?.toUtcIso(),
|
||||
canceledAt = it.canceledAt?.toUtcIso(),
|
||||
createdAt = it.createdAt?.toUtcIso()
|
||||
)
|
||||
},
|
||||
@@ -83,6 +86,9 @@ data class GiftListItemResponse(
|
||||
val counterpartMemberId: Long,
|
||||
val counterpartNickname: String,
|
||||
val counterpartProfileImageUrl: String,
|
||||
val recipientAddressRegistered: Boolean,
|
||||
val recipientAddressDeadlineAt: String?,
|
||||
val canceledAt: String?,
|
||||
val createdAt: String?
|
||||
)
|
||||
|
||||
|
||||
@@ -46,6 +46,9 @@ data class GiftListItemResult(
|
||||
val counterpartMemberId: Long,
|
||||
val counterpartNickname: String,
|
||||
val counterpartProfileImageUrl: String,
|
||||
val recipientAddressRegistered: Boolean,
|
||||
val recipientAddressDeadlineAt: LocalDateTime?,
|
||||
val canceledAt: LocalDateTime?,
|
||||
val createdAt: LocalDateTime?
|
||||
)
|
||||
|
||||
@@ -153,10 +156,13 @@ class GiftQueryService(
|
||||
val membersById = memberRepository.findAllById(
|
||||
gifts.content.flatMap { listOf(it.senderMemberId, it.recipientMemberId) }.toSet()
|
||||
).associateBy { it.id ?: throw invalidRequest() }
|
||||
val deliveriesByGiftId = deliveryRepository.findByGiftIdIn(
|
||||
gifts.content.mapNotNull { it.id }
|
||||
).associateBy { it.giftId }
|
||||
|
||||
return GiftListResult(
|
||||
totalCount = gifts.totalElements,
|
||||
items = gifts.content.map { it.toGiftListItem(memberId, membersById) },
|
||||
items = gifts.content.map { it.toGiftListItem(memberId, membersById, deliveriesByGiftId) },
|
||||
page = normalizedPage,
|
||||
size = normalizedSize,
|
||||
hasNext = gifts.hasNext()
|
||||
@@ -203,10 +209,16 @@ class GiftQueryService(
|
||||
)
|
||||
}
|
||||
|
||||
private fun Gift.toGiftListItem(memberId: Long, membersById: Map<Long, Member>): GiftListItemResult {
|
||||
private fun Gift.toGiftListItem(
|
||||
memberId: Long,
|
||||
membersById: Map<Long, Member>,
|
||||
deliveriesByGiftId: Map<Long, GiftDelivery>
|
||||
): GiftListItemResult {
|
||||
val direction = if (senderMemberId == memberId) GiftDirection.SENT else GiftDirection.RECEIVED
|
||||
val counterpartId = if (direction == GiftDirection.SENT) recipientMemberId else senderMemberId
|
||||
val counterpart = membersById[counterpartId] ?: throw invalidRequest()
|
||||
val delivery = deliveriesByGiftId[id] ?: throw invalidRequest()
|
||||
val recipientAddressRegistered = delivery.hasCompleteRecipientInformation()
|
||||
|
||||
return GiftListItemResult(
|
||||
applicationNo = applicationNo,
|
||||
@@ -219,6 +231,9 @@ class GiftQueryService(
|
||||
counterpartMemberId = counterpartId,
|
||||
counterpartNickname = counterpart.nickname,
|
||||
counterpartProfileImageUrl = counterpart.profileImageUrl(),
|
||||
recipientAddressRegistered = recipientAddressRegistered,
|
||||
recipientAddressDeadlineAt = delivery.recipientAddressDeadlineAt.takeUnless { recipientAddressRegistered },
|
||||
canceledAt = delivery.canceledAt,
|
||||
createdAt = createdAt
|
||||
)
|
||||
}
|
||||
|
||||
+28
-2
@@ -100,7 +100,18 @@ class GiftControllerTest @Autowired constructor(
|
||||
senderMemberId = member.id!!,
|
||||
recipientMemberId = counterpart.id!!,
|
||||
status = GiftStatus.RECEIVED
|
||||
)
|
||||
).also { gift ->
|
||||
giftDeliveryRepository.save(
|
||||
GiftDelivery(
|
||||
giftId = gift.id!!,
|
||||
senderName = "홍길동",
|
||||
senderPhoneNumber = "01012345678",
|
||||
senderZipCode = "06234",
|
||||
senderAddress = "서울시 강남구",
|
||||
trackingDeadlineAt = LocalDateTime.of(2026, 10, 2, 12, 0)
|
||||
)
|
||||
)
|
||||
}
|
||||
saveGift(
|
||||
"G-CONTROLLER-HIDDEN",
|
||||
senderMemberId = counterpart.id!!,
|
||||
@@ -112,7 +123,19 @@ class GiftControllerTest @Autowired constructor(
|
||||
senderMemberId = counterpart.id!!,
|
||||
recipientMemberId = member.id!!,
|
||||
status = GiftStatus.TRACKING_REGISTERED
|
||||
)
|
||||
).also { gift ->
|
||||
giftDeliveryRepository.save(
|
||||
GiftDelivery(
|
||||
giftId = gift.id!!,
|
||||
senderName = "홍길동",
|
||||
senderPhoneNumber = "01012345678",
|
||||
senderZipCode = "06234",
|
||||
senderAddress = "서울시 강남구",
|
||||
trackingDeadlineAt = LocalDateTime.of(2026, 10, 2, 12, 0),
|
||||
recipientAddressDeadlineAt = LocalDateTime.of(2026, 10, 7, 12, 0)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
mockMvc.perform(
|
||||
get("/api/v2/gifts")
|
||||
@@ -138,6 +161,9 @@ class GiftControllerTest @Autowired constructor(
|
||||
.andExpect(jsonPath("$.data.items[0].counterpartMemberId").value(counterpart.id!!))
|
||||
.andExpect(jsonPath("$.data.items[0].counterpartNickname").value("counterpart"))
|
||||
.andExpect(jsonPath("$.data.items[0].counterpartProfileImageUrl").value("https://cdn.test/profile/counterpart.png"))
|
||||
.andExpect(jsonPath("$.data.items[0].recipientAddressRegistered").value(false))
|
||||
.andExpect(jsonPath("$.data.items[0].recipientAddressDeadlineAt").value("2026-10-07T12:00:00Z"))
|
||||
.andExpect(jsonPath("$.data.items[0].canceledAt").isEmpty)
|
||||
.andExpect(jsonPath("$.data.items[0].createdAt").value(endsWith("Z")))
|
||||
}
|
||||
|
||||
|
||||
+88
-17
@@ -66,11 +66,13 @@ class GiftQueryServiceTest @Autowired constructor(
|
||||
fun shouldListReceivedGiftForSender() {
|
||||
val sender = saveMember("fan")
|
||||
val recipient = saveMember("creator", "profile/creator.png")
|
||||
saveGift(
|
||||
"G-SENT-RECEIVED",
|
||||
senderMemberId = sender.id!!,
|
||||
recipientMemberId = recipient.id!!,
|
||||
status = GiftStatus.RECEIVED
|
||||
saveDelivery(
|
||||
saveGift(
|
||||
"G-SENT-RECEIVED",
|
||||
senderMemberId = sender.id!!,
|
||||
recipientMemberId = recipient.id!!,
|
||||
status = GiftStatus.RECEIVED
|
||||
)
|
||||
)
|
||||
|
||||
val result = queryService().getGifts(
|
||||
@@ -107,11 +109,13 @@ class GiftQueryServiceTest @Autowired constructor(
|
||||
recipientMemberId = recipient.id!!,
|
||||
status = GiftStatus.RECEIVED
|
||||
)
|
||||
saveGift(
|
||||
"G-RECEIVED-VISIBLE",
|
||||
senderMemberId = visibleSender.id!!,
|
||||
recipientMemberId = recipient.id!!,
|
||||
status = GiftStatus.TRACKING_REGISTERED
|
||||
saveDelivery(
|
||||
saveGift(
|
||||
"G-RECEIVED-VISIBLE",
|
||||
senderMemberId = visibleSender.id!!,
|
||||
recipientMemberId = recipient.id!!,
|
||||
status = GiftStatus.TRACKING_REGISTERED
|
||||
)
|
||||
)
|
||||
|
||||
val result = queryService().getGifts(
|
||||
@@ -136,12 +140,21 @@ class GiftQueryServiceTest @Autowired constructor(
|
||||
val creator = saveMember("creator")
|
||||
val fan = saveMember("fan")
|
||||
val hiddenFan = saveMember("hidden-fan")
|
||||
saveGift("G-ALL-SENT", senderMemberId = member.id!!, recipientMemberId = creator.id!!, status = GiftStatus.CANCELED)
|
||||
saveGift(
|
||||
"G-ALL-RECEIVED",
|
||||
senderMemberId = fan.id!!,
|
||||
recipientMemberId = member.id!!,
|
||||
status = GiftStatus.ARRIVED_AT_MAILBOX
|
||||
saveDelivery(
|
||||
saveGift(
|
||||
"G-ALL-SENT",
|
||||
senderMemberId = member.id!!,
|
||||
recipientMemberId = creator.id!!,
|
||||
status = GiftStatus.CANCELED
|
||||
)
|
||||
)
|
||||
saveDelivery(
|
||||
saveGift(
|
||||
"G-ALL-RECEIVED",
|
||||
senderMemberId = fan.id!!,
|
||||
recipientMemberId = member.id!!,
|
||||
status = GiftStatus.ARRIVED_AT_MAILBOX
|
||||
)
|
||||
)
|
||||
saveGift("G-ALL-HIDDEN", senderMemberId = hiddenFan.id!!, recipientMemberId = member.id!!, status = GiftStatus.RECEIVED)
|
||||
|
||||
@@ -163,12 +176,70 @@ class GiftQueryServiceTest @Autowired constructor(
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("선물함 목록은 배송지 입력 여부와 기한, 취소일을 반환한다")
|
||||
fun shouldListRecipientAddressAndCancellationFields() {
|
||||
val member = saveMember("creator")
|
||||
val pendingSender = saveMember("pending-fan")
|
||||
val completedSender = saveMember("completed-fan")
|
||||
val canceledRecipient = saveMember("canceled-creator")
|
||||
val pendingGift = saveGift(
|
||||
"G-LIST-PENDING",
|
||||
senderMemberId = pendingSender.id!!,
|
||||
recipientMemberId = member.id!!,
|
||||
status = GiftStatus.TRACKING_REGISTERED
|
||||
)
|
||||
saveDelivery(pendingGift).apply {
|
||||
trackingRegisteredAt = NOW.plusHours(1)
|
||||
recipientAddressDeadlineAt = NOW.plusDays(7)
|
||||
}
|
||||
val completedGift = saveGift(
|
||||
"G-LIST-COMPLETE",
|
||||
senderMemberId = completedSender.id!!,
|
||||
recipientMemberId = member.id!!,
|
||||
status = GiftStatus.ARRIVED_AT_MAILBOX
|
||||
)
|
||||
saveDelivery(completedGift).apply {
|
||||
trackingRegisteredAt = NOW.plusHours(1)
|
||||
arrivedAtMailboxAt = NOW.plusHours(2)
|
||||
recipientAddressDeadlineAt = NOW.plusDays(7)
|
||||
recipientName = "수신자"
|
||||
recipientPhoneNumber = "01098765432"
|
||||
recipientZipCode = "04524"
|
||||
recipientAddress = "서울시 중구"
|
||||
}
|
||||
val canceledGift = saveGift(
|
||||
"G-LIST-CANCELED",
|
||||
senderMemberId = member.id!!,
|
||||
recipientMemberId = canceledRecipient.id!!,
|
||||
status = GiftStatus.CANCELED
|
||||
)
|
||||
saveDelivery(canceledGift).canceledAt = NOW.plusHours(3)
|
||||
|
||||
val result = queryService().getGifts(
|
||||
memberId = member.id!!,
|
||||
type = GiftListType.ALL,
|
||||
page = 0,
|
||||
size = 20
|
||||
)
|
||||
|
||||
val items = result.items.associateBy { it.applicationNo }
|
||||
assertEquals(false, items.getValue("G-LIST-PENDING").recipientAddressRegistered)
|
||||
assertEquals(NOW.plusDays(7), items.getValue("G-LIST-PENDING").recipientAddressDeadlineAt)
|
||||
assertNull(items.getValue("G-LIST-PENDING").canceledAt)
|
||||
assertEquals(true, items.getValue("G-LIST-COMPLETE").recipientAddressRegistered)
|
||||
assertNull(items.getValue("G-LIST-COMPLETE").recipientAddressDeadlineAt)
|
||||
assertEquals(NOW.plusHours(3), items.getValue("G-LIST-CANCELED").canceledAt)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("선물함 page와 size는 음수 또는 0이면 기본값으로 보정된다")
|
||||
fun shouldNormalizeGiftListPageAndSize() {
|
||||
val sender = saveMember("fan")
|
||||
val recipient = saveMember("creator")
|
||||
saveGift("G-PAGING", senderMemberId = sender.id!!, recipientMemberId = recipient.id!!, status = GiftStatus.RECEIVED)
|
||||
saveDelivery(
|
||||
saveGift("G-PAGING", senderMemberId = sender.id!!, recipientMemberId = recipient.id!!, status = GiftStatus.RECEIVED)
|
||||
)
|
||||
|
||||
val result = queryService().getGifts(
|
||||
memberId = sender.id!!,
|
||||
|
||||
Reference in New Issue
Block a user