feat(gift): 관리자 선물 취소와 발신자 환불을 추가한다
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.gift.application
|
package kr.co.vividnext.sodalive.v2.gift.application
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.can.payment.CanPaymentService
|
||||||
import kr.co.vividnext.sodalive.common.SodaException
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
import kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence.GiftCategory
|
import kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence.GiftCategory
|
||||||
import kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence.GiftCategoryRepository
|
import kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence.GiftCategoryRepository
|
||||||
@@ -73,7 +74,8 @@ class GiftAdminService(
|
|||||||
private val giftRepository: GiftRepository,
|
private val giftRepository: GiftRepository,
|
||||||
private val giftDeliveryRepository: GiftDeliveryRepository,
|
private val giftDeliveryRepository: GiftDeliveryRepository,
|
||||||
private val giftMailboxRepository: GiftMailboxRepository,
|
private val giftMailboxRepository: GiftMailboxRepository,
|
||||||
private val giftPushService: GiftPushService
|
private val giftPushService: GiftPushService,
|
||||||
|
private val canPaymentService: CanPaymentService
|
||||||
) {
|
) {
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
fun getMailbox(): GiftMailboxResult? = giftMailboxRepository.findByIdOrNull(GiftMailbox.SINGLETON_ID)?.toResult()
|
fun getMailbox(): GiftMailboxResult? = giftMailboxRepository.findByIdOrNull(GiftMailbox.SINGLETON_ID)?.toResult()
|
||||||
@@ -150,6 +152,19 @@ class GiftAdminService(
|
|||||||
return sizePriceRepository.save(sizePrice).toResult()
|
return sizePriceRepository.save(sizePrice).toResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
fun cancelGift(applicationNo: String, now: LocalDateTime = LocalDateTime.now()): GiftOperationStatusResult {
|
||||||
|
val gift = giftRepository.findByApplicationNoForUpdate(applicationNo) ?: throw invalidRequest()
|
||||||
|
if (gift.status != GiftStatus.RECEIVED) throw invalidRequest()
|
||||||
|
val delivery = giftDeliveryRepository.findByGiftId(requireNotNull(gift.id)) ?: throw invalidRequest()
|
||||||
|
|
||||||
|
gift.status = GiftStatus.CANCELED
|
||||||
|
delivery.canceledAt = now
|
||||||
|
canPaymentService.refundGiftCan(gift.senderMemberId, gift.canUsageId)
|
||||||
|
|
||||||
|
return GiftOperationStatusResult(gift.applicationNo, gift.status, gift.status.displayName, now)
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
fun arriveMailbox(applicationNo: String, now: LocalDateTime = LocalDateTime.now()): GiftOperationStatusResult {
|
fun arriveMailbox(applicationNo: String, now: LocalDateTime = LocalDateTime.now()): GiftOperationStatusResult {
|
||||||
val gift = giftRepository.findByApplicationNo(applicationNo) ?: throw invalidRequest()
|
val gift = giftRepository.findByApplicationNo(applicationNo) ?: throw invalidRequest()
|
||||||
|
|||||||
+44
-1
@@ -1,5 +1,6 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.gift.application
|
package kr.co.vividnext.sodalive.v2.gift.application
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.can.payment.CanPaymentService
|
||||||
import kr.co.vividnext.sodalive.common.SodaException
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
import kr.co.vividnext.sodalive.configs.QueryDslConfig
|
import kr.co.vividnext.sodalive.configs.QueryDslConfig
|
||||||
import kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence.Gift
|
import kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence.Gift
|
||||||
@@ -17,6 +18,7 @@ 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.ParameterizedTest
|
||||||
|
import org.junit.jupiter.params.provider.EnumSource
|
||||||
import org.junit.jupiter.params.provider.ValueSource
|
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
|
||||||
@@ -40,13 +42,15 @@ class GiftAdminServiceTest @Autowired constructor(
|
|||||||
private val giftMailboxRepository: GiftMailboxRepository
|
private val giftMailboxRepository: GiftMailboxRepository
|
||||||
) {
|
) {
|
||||||
private val giftPushService = Mockito.mock(GiftPushService::class.java)
|
private val giftPushService = Mockito.mock(GiftPushService::class.java)
|
||||||
|
private val canPaymentService = Mockito.mock(CanPaymentService::class.java)
|
||||||
private val service = GiftAdminService(
|
private val service = GiftAdminService(
|
||||||
categoryRepository,
|
categoryRepository,
|
||||||
sizePriceRepository,
|
sizePriceRepository,
|
||||||
giftRepository,
|
giftRepository,
|
||||||
giftDeliveryRepository,
|
giftDeliveryRepository,
|
||||||
giftMailboxRepository,
|
giftMailboxRepository,
|
||||||
giftPushService
|
giftPushService,
|
||||||
|
canPaymentService
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -312,6 +316,45 @@ class GiftAdminServiceTest @Autowired constructor(
|
|||||||
Mockito.verifyNoInteractions(giftPushService)
|
Mockito.verifyNoInteractions(giftPushService)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("운영자는 접수 선물을 취소하고 원 발신자의 결제 내역을 한 번 환불한다")
|
||||||
|
fun shouldCancelReceivedGiftWithOriginalSenderRefund() {
|
||||||
|
val (gift, delivery) = saveGift(GiftStatus.RECEIVED)
|
||||||
|
|
||||||
|
val result = service.cancelGift(APPLICATION_NO, NOW)
|
||||||
|
|
||||||
|
assertEquals(GiftOperationStatusResult(APPLICATION_NO, GiftStatus.CANCELED, "신청 취소", NOW), result)
|
||||||
|
assertEquals(GiftStatus.CANCELED, gift.status)
|
||||||
|
assertEquals(NOW, delivery.canceledAt)
|
||||||
|
assertThrows(SodaException::class.java) { service.cancelGift(APPLICATION_NO, NOW.plusSeconds(1)) }
|
||||||
|
assertEquals(NOW, delivery.canceledAt)
|
||||||
|
Mockito.verify(canPaymentService, Mockito.times(1)).refundGiftCan(SENDER_MEMBER_ID, 10L)
|
||||||
|
Mockito.verifyNoInteractions(giftPushService)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@EnumSource(value = GiftStatus::class, names = ["RECEIVED"], mode = EnumSource.Mode.EXCLUDE)
|
||||||
|
@DisplayName("운영자는 접수가 아닌 모든 상태의 선물을 취소할 수 없다")
|
||||||
|
fun shouldRejectCancellationForEveryNonReceivedStatus(status: GiftStatus) {
|
||||||
|
val (gift, delivery) = saveGift(status)
|
||||||
|
|
||||||
|
val exception = assertThrows(SodaException::class.java) { service.cancelGift(APPLICATION_NO, NOW) }
|
||||||
|
|
||||||
|
assertEquals("common.error.invalid_request", exception.messageKey)
|
||||||
|
assertEquals(status, gift.status)
|
||||||
|
assertEquals(null, delivery.canceledAt)
|
||||||
|
Mockito.verifyNoInteractions(canPaymentService, giftPushService)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("운영자는 없는 선물을 취소할 수 없다")
|
||||||
|
fun shouldRejectCancellationForMissingGift() {
|
||||||
|
val exception = assertThrows(SodaException::class.java) { service.cancelGift("missing", NOW) }
|
||||||
|
|
||||||
|
assertEquals("common.error.invalid_request", exception.messageKey)
|
||||||
|
Mockito.verifyNoInteractions(canPaymentService, giftPushService)
|
||||||
|
}
|
||||||
|
|
||||||
private fun populateRecipientInformation(delivery: GiftDelivery) {
|
private fun populateRecipientInformation(delivery: GiftDelivery) {
|
||||||
delivery.recipientName = "김소다"
|
delivery.recipientName = "김소다"
|
||||||
delivery.recipientPhoneNumber = "01098765432"
|
delivery.recipientPhoneNumber = "01098765432"
|
||||||
|
|||||||
Reference in New Issue
Block a user