feat(gift): 배송 개인정보의 null 저장과 조회 호환을 지원한다

This commit is contained in:
2026-10-26 08:44:44 +09:00
parent c837ff18f8
commit f46a6c4c7c
8 changed files with 312 additions and 20 deletions
@@ -128,3 +128,11 @@ CREATE TABLE gift_application_no_sequence (
) COMMENT='선물 신청번호 날짜별 채번'; ) COMMENT='선물 신청번호 날짜별 채번';
ALTER TABLE gift_category DROP INDEX uk_gift_category_receipt_code; ALTER TABLE gift_category DROP INDEX uk_gift_category_receipt_code;
-- 2026-10-23: 전달 완료 후 배송정보 삭제를 위한 발신자 컬럼 NULL 허용.
-- 기존 DB에는 아래 ALTER TABLE 문만 적용하며, 이 파일 전체를 재실행하지 않는다.
ALTER TABLE gift_delivery
MODIFY COLUMN sender_name VARCHAR(50) NULL COMMENT '발신자 이름',
MODIFY COLUMN sender_phone_number VARCHAR(30) NULL COMMENT '발신자 휴대폰 번호',
MODIFY COLUMN sender_zip_code VARCHAR(20) NULL COMMENT '발신자 우편번호',
MODIFY COLUMN sender_address VARCHAR(255) NULL COMMENT '발신자 주소';
@@ -16,20 +16,20 @@ class GiftDelivery(
@Column(name = "gift_id", nullable = false) @Column(name = "gift_id", nullable = false)
val giftId: Long, val giftId: Long,
@Column(name = "sender_name", nullable = false, length = 50) @Column(name = "sender_name", length = 50)
val senderName: String, var senderName: String?,
@Column(name = "sender_phone_number", nullable = false, length = 30) @Column(name = "sender_phone_number", length = 30)
val senderPhoneNumber: String, var senderPhoneNumber: String?,
@Column(name = "sender_zip_code", nullable = false, length = 20) @Column(name = "sender_zip_code", length = 20)
val senderZipCode: String, var senderZipCode: String?,
@Column(name = "sender_address", nullable = false, length = 255) @Column(name = "sender_address", length = 255)
val senderAddress: String, var senderAddress: String?,
@Column(name = "sender_address_detail", length = 255) @Column(name = "sender_address_detail", length = 255)
val senderAddressDetail: String? = null, var senderAddressDetail: String? = null,
@Column(name = "recipient_name", length = 50) @Column(name = "recipient_name", length = 50)
var recipientName: String? = null, var recipientName: String? = null,
@@ -115,8 +115,8 @@ class GiftAdminQueryService(
applicationNo = gift.applicationNo, applicationNo = gift.applicationNo,
senderInfo = AdminGiftMemberInfoResult( senderInfo = AdminGiftMemberInfoResult(
nickname = sender.nickname, nickname = sender.nickname,
name = delivery.senderName, name = delivery.senderName.orEmpty(),
phoneNumber = delivery.senderPhoneNumber, phoneNumber = delivery.senderPhoneNumber.orEmpty(),
address = formatAddress(delivery.senderZipCode, delivery.senderAddress, delivery.senderAddressDetail) address = formatAddress(delivery.senderZipCode, delivery.senderAddress, delivery.senderAddressDetail)
), ),
recipientInfo = AdminGiftMemberInfoResult( recipientInfo = AdminGiftMemberInfoResult(
@@ -174,8 +174,8 @@ class GiftAdminQueryService(
return formatAddress(zipCode, address, recipientAddressDetail) return formatAddress(zipCode, address, recipientAddressDetail)
} }
private fun formatAddress(zipCode: String, address: String, detail: String?) = private fun formatAddress(zipCode: String?, address: String?, detail: String?) =
"($zipCode) $address" + if (detail.isNullOrBlank()) "" else ", $detail" if (zipCode == null || address == null) "" else "($zipCode) $address" + if (detail.isNullOrBlank()) "" else ", $detail"
private fun invalidRequest() = SodaException(messageKey = "common.error.invalid_request") private fun invalidRequest() = SodaException(messageKey = "common.error.invalid_request")
@@ -259,8 +259,8 @@ class GiftQueryService(
} }
private fun GiftDelivery.toSenderInfo() = GiftAddressResult( private fun GiftDelivery.toSenderInfo() = GiftAddressResult(
name = senderName, name = senderName.orEmpty(),
phoneNumber = senderPhoneNumber, phoneNumber = senderPhoneNumber.orEmpty(),
address = formatAddress(senderZipCode, senderAddress, senderAddressDetail) address = formatAddress(senderZipCode, senderAddress, senderAddressDetail)
) )
@@ -305,8 +305,8 @@ class GiftQueryService(
) )
} }
private fun formatAddress(zipCode: String, address: String, detail: String?) = private fun formatAddress(zipCode: String?, address: String?, detail: String?) =
"($zipCode) $address" + if (detail.isNullOrBlank()) "" else ", $detail" if (zipCode == null || address == null) "" else "($zipCode) $address" + if (detail.isNullOrBlank()) "" else ", $detail"
private fun invalidRequest() = SodaException(messageKey = "common.error.invalid_request") private fun invalidRequest() = SodaException(messageKey = "common.error.invalid_request")
@@ -29,8 +29,11 @@ import kr.co.vividnext.sodalive.v2.gift.application.GiftTrackingRegistrationResu
import kr.co.vividnext.sodalive.v2.gift.domain.GiftSize import kr.co.vividnext.sodalive.v2.gift.domain.GiftSize
import kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus import kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus
import org.hamcrest.Matchers.endsWith import org.hamcrest.Matchers.endsWith
import org.hamcrest.Matchers.nullValue
import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
import org.mockito.Mockito import org.mockito.Mockito
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
@@ -219,6 +222,84 @@ class GiftControllerTest @Autowired constructor(
.andExpect(jsonPath("$.data.statusTimeline[1].occurredAt").value("2026-09-30T12:00:00Z")) .andExpect(jsonPath("$.data.statusTimeline[1].occurredAt").value("2026-09-30T12:00:00Z"))
} }
@Test
@DisplayName("배송 개인정보가 지워져도 보낸 선물과 받은 선물의 상세 응답 계약을 유지한다")
fun shouldReturnCompatibleErasedGiftDetailsForSenderAndRecipient() {
val sender = memberRepository.save(Member(password = "password", nickname = "erased-fan"))
val recipient = memberRepository.save(Member(password = "password", nickname = "erased-creator"))
val gift = saveGift("G-CONTROLLER-ERASED", sender.id!!, recipient.id!!, GiftStatus.DELIVERED)
val delivery = GiftDelivery(
giftId = gift.id!!,
senderName = null,
senderPhoneNumber = null,
senderZipCode = null,
senderAddress = null,
trackingDeadlineAt = LocalDateTime.of(2026, 10, 2, 12, 0),
recipientAddressDeadlineAt = LocalDateTime.of(2026, 10, 7, 12, 0),
deliveredAt = LocalDateTime.of(2026, 10, 3, 12, 0)
)
giftDeliveryRepository.saveAndFlush(delivery)
mockMvc.perform(get("/api/v2/gifts/{applicationNo}", gift.applicationNo).with(user(MemberAdapter(sender))))
.andExpect(status().isOk)
.andExpect(jsonPath("$.success").value(true))
.andExpect(jsonPath("$.data.direction").value("SENT"))
.andExpect(jsonPath("$.data.status").value("DELIVERED"))
.andExpect(jsonPath("$.data.senderInfo").isMap)
.andExpect(jsonPath("$.data.senderInfo.name").value(""))
.andExpect(jsonPath("$.data.senderInfo.phoneNumber").value(""))
.andExpect(jsonPath("$.data.senderInfo.address").value(""))
.andExpect(jsonPath("$.data.recipientAddress").value(nullValue()))
.andExpect(jsonPath("$.data.giftInfo.tracking").value(nullValue()))
.andExpect(jsonPath("$.data.giftInfo.recipientCreatorNickname").value("erased-creator"))
.andExpect(jsonPath("$.data.trackingRequired").value(false))
.andExpect(jsonPath("$.data.recipientAddressRequired").value(false))
.andExpect(jsonPath("$.data.mailbox").value(nullValue()))
.andExpect(jsonPath("$.data.statusTimeline[4].occurredAt").value("2026-10-03T12:00:00Z"))
mockMvc.perform(get("/api/v2/gifts/{applicationNo}", gift.applicationNo).with(user(MemberAdapter(recipient))))
.andExpect(status().isOk)
.andExpect(jsonPath("$.success").value(true))
.andExpect(jsonPath("$.data.direction").value("RECEIVED"))
.andExpect(jsonPath("$.data.senderInfo").value(nullValue()))
.andExpect(jsonPath("$.data.recipientAddress").value(nullValue()))
.andExpect(jsonPath("$.data.giftInfo.tracking").value(nullValue()))
.andExpect(jsonPath("$.data.giftInfo.senderNickname").value("erased-fan"))
.andExpect(jsonPath("$.data.trackingRequired").value(false))
.andExpect(jsonPath("$.data.recipientAddressRequired").value(false))
.andExpect(jsonPath("$.data.recipientAddressDeadlineAt").value("2026-10-07T12:00:00Z"))
}
@ParameterizedTest
@ValueSource(strings = ["senderName", "senderPhoneNumber", "senderZipCode", "senderAddress"])
@DisplayName("저장 필드가 nullable이어도 신청의 필수 발신자 입력 누락을 거부한다")
fun shouldKeepRequiredSenderRequestValidation(missingField: String) {
val member = Member(password = "password", nickname = "fan").apply { id = SENDER_ID }
val request = objectMapper.createObjectNode()
.put("recipientMemberId", RECIPIENT_ID)
.put("senderName", "sender")
.put("senderPhoneNumber", "phone")
.put("senderZipCode", "zip")
.put("senderAddress", "address")
.put("sizeCode", "SMALL")
.put("categoryId", CATEGORY_ID)
.put("senderTermsAgreed", true)
.put("senderPrivacyAgreed", true)
.put("damageWaiverAgreed", true)
request.remove(missingField)
mockMvc.perform(
post("/api/v2/gifts")
.with(user(MemberAdapter(member)))
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request))
)
.andExpect(status().isOk)
.andExpect(jsonPath("$.success").value(false))
Mockito.verifyNoInteractions(commandService)
}
@Test @Test
@DisplayName("발신자는 전달 완료 전 정상 진행 선물 상세에서 받을 주소를 조회한다") @DisplayName("발신자는 전달 완료 전 정상 진행 선물 상세에서 받을 주소를 조회한다")
fun shouldGetMailboxForSentNormalProgressGiftDetailBeforeDelivered() { fun shouldGetMailboxForSentNormalProgressGiftDetailBeforeDelivered() {
@@ -5,6 +5,7 @@ import kr.co.vividnext.sodalive.v2.gift.domain.GiftSize
import kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus import kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus
import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Assertions.assertThrows import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@@ -13,6 +14,7 @@ import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.context.annotation.Import import org.springframework.context.annotation.Import
import org.springframework.dao.DataIntegrityViolationException import org.springframework.dao.DataIntegrityViolationException
import java.time.LocalDateTime import java.time.LocalDateTime
import javax.persistence.EntityManager
@DataJpaTest( @DataJpaTest(
properties = [ properties = [
@@ -28,7 +30,8 @@ class GiftEntityMappingTest @Autowired constructor(
private val giftCategoryRepository: GiftCategoryRepository, private val giftCategoryRepository: GiftCategoryRepository,
private val giftSizePriceRepository: GiftSizePriceRepository, private val giftSizePriceRepository: GiftSizePriceRepository,
private val giftReviewRepository: GiftReviewRepository, private val giftReviewRepository: GiftReviewRepository,
private val giftApplicationNoSequenceRepository: GiftApplicationNoSequenceRepository private val giftApplicationNoSequenceRepository: GiftApplicationNoSequenceRepository,
private val entityManager: EntityManager
) { ) {
@Test @Test
@DisplayName("선물 엔티티와 배송 정보를 저장하고 조회한다") @DisplayName("선물 엔티티와 배송 정보를 저장하고 조회한다")
@@ -91,6 +94,63 @@ class GiftEntityMappingTest @Autowired constructor(
assertNotNull(saved.updatedAt) assertNotNull(saved.updatedAt)
} }
@Test
@DisplayName("발신자와 수신자 및 운송장 개인정보를 모두 null로 저장하고 다시 조회한다")
fun shouldPersistNullForAllSenderFields() {
val category = giftCategoryRepository.save(giftCategory("100", "DOLL", "A"))
val gift = giftRepository.save(gift(category.id!!, "G-NULL-DELIVERY"))
val deadline = LocalDateTime.of(2026, 10, 2, 12, 0)
val delivery = giftDeliveryRepository.saveAndFlush(
GiftDelivery(
giftId = gift.id!!,
senderName = "sender",
senderPhoneNumber = "sender-phone",
senderZipCode = "sender-zip",
senderAddress = "sender-address",
senderAddressDetail = "sender-detail",
recipientName = "recipient",
recipientPhoneNumber = "recipient-phone",
recipientZipCode = "recipient-zip",
recipientAddress = "recipient-address",
recipientAddressDetail = "recipient-detail",
courierCompanyName = "courier",
trackingNumber = "tracking",
trackingDeadlineAt = deadline
)
)
delivery.senderName = null
delivery.senderPhoneNumber = null
delivery.senderZipCode = null
delivery.senderAddress = null
delivery.senderAddressDetail = null
delivery.recipientName = null
delivery.recipientPhoneNumber = null
delivery.recipientZipCode = null
delivery.recipientAddress = null
delivery.recipientAddressDetail = null
delivery.courierCompanyName = null
delivery.trackingNumber = null
entityManager.flush()
entityManager.clear()
val reloaded = requireNotNull(giftDeliveryRepository.findByGiftId(gift.id!!))
assertNull(reloaded.senderName)
assertNull(reloaded.senderPhoneNumber)
assertNull(reloaded.senderZipCode)
assertNull(reloaded.senderAddress)
assertNull(reloaded.senderAddressDetail)
assertNull(reloaded.recipientName)
assertNull(reloaded.recipientPhoneNumber)
assertNull(reloaded.recipientZipCode)
assertNull(reloaded.recipientAddress)
assertNull(reloaded.recipientAddressDetail)
assertNull(reloaded.courierCompanyName)
assertNull(reloaded.trackingNumber)
assertEquals(false, reloaded.hasCompleteRecipientInformation())
assertEquals(deadline, reloaded.trackingDeadlineAt)
}
@Test @Test
@DisplayName("신청번호와 카테고리 분류번호 및 코드와 리뷰 선물 ID는 중복 저장할 수 없다") @DisplayName("신청번호와 카테고리 분류번호 및 코드와 리뷰 선물 ID는 중복 저장할 수 없다")
fun shouldRejectDuplicateUniqueValues() { fun shouldRejectDuplicateUniqueValues() {
@@ -13,13 +13,18 @@ import kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence.GiftRepository
import kr.co.vividnext.sodalive.v2.gift.domain.GiftSize import kr.co.vividnext.sodalive.v2.gift.domain.GiftSize
import kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus import kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus
import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Assertions.assertThrows import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.NullAndEmptySource
import org.junit.jupiter.params.provider.ValueSource
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.context.annotation.Import import org.springframework.context.annotation.Import
import java.time.LocalDateTime import java.time.LocalDateTime
import javax.persistence.EntityManager
@DataJpaTest( @DataJpaTest(
properties = [ properties = [
@@ -33,7 +38,8 @@ class GiftAdminQueryServiceTest @Autowired constructor(
private val giftRepository: GiftRepository, private val giftRepository: GiftRepository,
private val deliveryRepository: GiftDeliveryRepository, private val deliveryRepository: GiftDeliveryRepository,
private val categoryRepository: GiftCategoryRepository, private val categoryRepository: GiftCategoryRepository,
private val memberRepository: MemberRepository private val memberRepository: MemberRepository,
private val entityManager: EntityManager
) { ) {
@Test @Test
@DisplayName("관리자는 선물함 목록을 필터링하고 가능한 액션을 조회한다") @DisplayName("관리자는 선물함 목록을 필터링하고 가능한 액션을 조회한다")
@@ -124,6 +130,51 @@ class GiftAdminQueryServiceTest @Autowired constructor(
assertEquals(listOf("COMPLETE_INSPECTION", "MARK_UNDELIVERABLE"), result.availableActions) assertEquals(listOf("COMPLETE_INSPECTION", "MARK_UNDELIVERABLE"), result.availableActions)
} }
@Test
@DisplayName("개인정보가 지워진 관리자 선물 응답은 닉네임과 종료 상태 액션을 유지한다")
fun shouldMapErasedDeliveryStringsWithoutChangingActions() {
val sender = saveMember("fan-alpha")
val recipient = saveMember("creator-alpha")
val gift = saveGift("A-ERASED-DETAIL", sender, recipient, saveCategory(), GiftStatus.DELIVERED)
requireNotNull(deliveryRepository.findByGiftId(gift.id!!)).apply {
senderName = null
senderPhoneNumber = null
senderZipCode = null
senderAddress = null
senderAddressDetail = null
}
entityManager.flush()
entityManager.clear()
val detail = service().getGiftDetail(gift.applicationNo)
val item = service().getGifts(GiftStatus.DELIVERED, null, null, 0, 20).items.single()
assertEquals(AdminGiftMemberInfoResult("fan-alpha", "", "", ""), detail.senderInfo)
assertEquals(AdminGiftMemberInfoResult("creator-alpha", "", "", ""), detail.recipientInfo)
assertNull(detail.inboundDeliveryInfo.courierCompanyName)
assertNull(detail.inboundDeliveryInfo.trackingNumber)
assertEquals(GiftStatus.DELIVERED, detail.status)
assertEquals(emptyList<String>(), detail.availableActions)
assertEquals("fan-alpha", item.senderNickname)
assertEquals("creator-alpha", item.recipientNickname)
assertNull(item.courierCompanyName)
assertNull(item.trackingNumber)
assertEquals(emptyList<String>(), item.availableActions)
}
@ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = [" "])
@DisplayName("관리자 발신자 주소도 상세주소가 없으면 구분자를 생략한다")
fun shouldOmitAbsentSenderAddressDetail(detail: String?) {
val gift = saveGift("A-NO-DETAIL", saveMember("fan"), saveMember("creator"), saveCategory(), GiftStatus.RECEIVED)
requireNotNull(deliveryRepository.findByGiftId(gift.id!!)).senderAddressDetail = detail
val result = service().getGiftDetail(gift.applicationNo)
assertEquals("(06234) 서울시 강남구", result.senderInfo.address)
}
@Test @Test
@DisplayName("관리자 선물 목록과 상세는 상태별 가능한 액션을 반환하고 없는 신청번호를 거부한다") @DisplayName("관리자 선물 목록과 상세는 상태별 가능한 액션을 반환하고 없는 신청번호를 거부한다")
fun shouldReturnAvailableActionsByStatusAndRejectUnknownApplicationNo() { fun shouldReturnAvailableActionsByStatusAndRejectUnknownApplicationNo() {
@@ -27,10 +27,14 @@ import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Assertions.assertThrows import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.NullAndEmptySource
import org.junit.jupiter.params.provider.ValueSource
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.context.annotation.Import import org.springframework.context.annotation.Import
import java.time.LocalDateTime import java.time.LocalDateTime
import javax.persistence.EntityManager
@DataJpaTest( @DataJpaTest(
properties = [ properties = [
@@ -46,7 +50,8 @@ class GiftQueryServiceTest @Autowired constructor(
private val deliveryRepository: GiftDeliveryRepository, private val deliveryRepository: GiftDeliveryRepository,
private val memberRepository: MemberRepository, private val memberRepository: MemberRepository,
private val giftMailboxRepository: GiftMailboxRepository, private val giftMailboxRepository: GiftMailboxRepository,
private val creatorLocalizedNameService: CreatorLocalizedNameService private val creatorLocalizedNameService: CreatorLocalizedNameService,
private val entityManager: EntityManager
) { ) {
@Test @Test
fun `폼 옵션은 활성 카테고리와 활성 사이즈 가격만 반환한다`() { fun `폼 옵션은 활성 카테고리와 활성 사이즈 가격만 반환한다`() {
@@ -313,6 +318,93 @@ class GiftQueryServiceTest @Autowired constructor(
assertNull(result.statusTimeline[1].occurredAt) assertNull(result.statusTimeline[1].occurredAt)
} }
@Test
@DisplayName("개인정보가 지워진 보낸 선물은 발신자 객체와 빈 문자열을 유지한다")
fun shouldMapErasedSentSenderDetailsToEmptyStrings() {
val sender = saveMember("fan")
val recipient = saveMember("creator", "profile/creator.png")
val gift = saveGift("G-ERASED-SENT", sender.id!!, recipient.id!!, GiftStatus.DELIVERED)
saveDelivery(gift).apply {
applyStatusTimes(GiftStatus.DELIVERED)
recipientAddressDeadlineAt = NOW.plusDays(7)
senderName = null
senderPhoneNumber = null
senderZipCode = null
senderAddress = null
senderAddressDetail = null
}
entityManager.flush()
entityManager.clear()
val result = queryService().getGiftDetail(sender.id!!, gift.applicationNo, Lang.KO)
val item = queryService().getGifts(sender.id!!, GiftListType.SENT, 0, 20, Lang.KO).items.single()
assertEquals(GiftDirection.SENT, result.direction)
assertEquals(GiftStatus.DELIVERED, result.status)
assertEquals(GiftAddressResult("", "", ""), result.senderInfo)
assertNull(result.recipientAddress)
assertNull(result.giftInfo.tracking)
assertNull(result.mailbox)
assertEquals("creator", result.giftInfo.recipientCreatorNickname)
assertEquals(false, result.trackingRequired)
assertEquals(false, result.recipientAddressRequired)
assertEquals(NOW.plusHours(4), result.statusTimeline.last().occurredAt)
assertEquals("creator", item.counterpartNickname)
assertEquals("https://cdn.test/profile/creator.png", item.counterpartProfileImageUrl)
assertEquals(false, item.recipientAddressRegistered)
assertEquals(NOW.plusDays(7), item.recipientAddressDeadlineAt)
}
@Test
@DisplayName("개인정보가 지워진 받은 선물은 발신자 정보와 수신자 배송지를 null로 유지한다")
fun shouldKeepReceivedSenderInfoNullAndRecipientAddressNullWhenErased() {
val sender = saveMember("fan", "profile/fan.png")
val recipient = saveMember("creator")
val gift = saveGift("G-ERASED-RECEIVED", sender.id!!, recipient.id!!, GiftStatus.DELIVERED)
saveDelivery(gift).apply {
applyStatusTimes(GiftStatus.DELIVERED)
recipientAddressDeadlineAt = NOW.plusDays(7)
senderName = null
senderPhoneNumber = null
senderZipCode = null
senderAddress = null
senderAddressDetail = null
}
entityManager.flush()
entityManager.clear()
val result = queryService().getGiftDetail(recipient.id!!, gift.applicationNo, Lang.KO)
val item = queryService().getGifts(recipient.id!!, GiftListType.RECEIVED, 0, 20, Lang.KO).items.single()
assertEquals(GiftDirection.RECEIVED, result.direction)
assertNull(result.senderInfo)
assertNull(result.recipientAddress)
assertNull(result.giftInfo.tracking)
assertEquals("fan", result.giftInfo.senderNickname)
assertEquals(false, result.trackingRequired)
assertEquals(false, result.recipientAddressRequired)
assertEquals(NOW.plusDays(7), result.recipientAddressDeadlineAt)
assertEquals("fan", item.counterpartNickname)
assertEquals("https://cdn.test/profile/fan.png", item.counterpartProfileImageUrl)
assertEquals(false, item.recipientAddressRegistered)
assertEquals(NOW.plusDays(7), item.recipientAddressDeadlineAt)
}
@ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = [" "])
@DisplayName("발신자 상세주소가 없으면 주소 뒤 구분자를 생략한다")
fun shouldOmitAbsentSenderAddressDetail(detail: String?) {
val sender = saveMember("fan")
val recipient = saveMember("creator")
val gift = saveGift("G-NO-ADDRESS-DETAIL", sender.id!!, recipient.id!!, GiftStatus.RECEIVED)
saveDelivery(gift).senderAddressDetail = detail
val result = queryService().getGiftDetail(sender.id!!, gift.applicationNo, Lang.KO)
assertEquals("(06234) 서울시 강남구", result.senderInfo?.address)
}
@Test @Test
@DisplayName("보낸 선물의 전달 완료 전 정상 진행 상세는 받을 주소를 반환한다") @DisplayName("보낸 선물의 전달 완료 전 정상 진행 상세는 받을 주소를 반환한다")
fun shouldReturnMailboxForSentNormalProgressGiftDetailBeforeDelivered() { fun shouldReturnMailboxForSentNormalProgressGiftDetailBeforeDelivered() {