feat(gift): 선물 배송과 리뷰 저장소를 추가한다
This commit is contained in:
+87
@@ -0,0 +1,87 @@
|
||||
package kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence
|
||||
|
||||
import kr.co.vividnext.sodalive.common.BaseEntity
|
||||
import java.time.LocalDateTime
|
||||
import javax.persistence.Column
|
||||
import javax.persistence.Entity
|
||||
import javax.persistence.Table
|
||||
import javax.persistence.UniqueConstraint
|
||||
|
||||
@Entity
|
||||
@Table(
|
||||
name = "gift_delivery",
|
||||
uniqueConstraints = [UniqueConstraint(name = "uk_gift_delivery_gift_id", columnNames = ["gift_id"])]
|
||||
)
|
||||
class GiftDelivery(
|
||||
@Column(name = "gift_id", nullable = false)
|
||||
val giftId: Long,
|
||||
|
||||
@Column(name = "sender_name", nullable = false, length = 50)
|
||||
val senderName: String,
|
||||
|
||||
@Column(name = "sender_phone_number", nullable = false, length = 30)
|
||||
val senderPhoneNumber: String,
|
||||
|
||||
@Column(name = "sender_zip_code", nullable = false, length = 20)
|
||||
val senderZipCode: String,
|
||||
|
||||
@Column(name = "sender_address", nullable = false, length = 255)
|
||||
val senderAddress: String,
|
||||
|
||||
@Column(name = "sender_address_detail", length = 255)
|
||||
val senderAddressDetail: String? = null,
|
||||
|
||||
@Column(name = "recipient_name", length = 50)
|
||||
var recipientName: String? = null,
|
||||
|
||||
@Column(name = "recipient_phone_number", length = 30)
|
||||
var recipientPhoneNumber: String? = null,
|
||||
|
||||
@Column(name = "recipient_zip_code", length = 20)
|
||||
var recipientZipCode: String? = null,
|
||||
|
||||
@Column(name = "recipient_address", length = 255)
|
||||
var recipientAddress: String? = null,
|
||||
|
||||
@Column(name = "recipient_address_detail", length = 255)
|
||||
var recipientAddressDetail: String? = null,
|
||||
|
||||
@Column(name = "courier_company_name", length = 50)
|
||||
var courierCompanyName: String? = null,
|
||||
|
||||
@Column(name = "tracking_number", length = 100)
|
||||
var trackingNumber: String? = null,
|
||||
|
||||
@Column(name = "tracking_deadline_at", nullable = false)
|
||||
val trackingDeadlineAt: LocalDateTime,
|
||||
|
||||
@Column(name = "recipient_address_deadline_at")
|
||||
var recipientAddressDeadlineAt: LocalDateTime? = null,
|
||||
|
||||
@Column(name = "tracking_deadline_reminder_sent_at")
|
||||
var trackingDeadlineReminderSentAt: LocalDateTime? = null,
|
||||
|
||||
@Column(name = "recipient_address_deadline_reminder_sent_at")
|
||||
var recipientAddressDeadlineReminderSentAt: LocalDateTime? = null,
|
||||
|
||||
@Column(name = "tracking_registered_at")
|
||||
var trackingRegisteredAt: LocalDateTime? = null,
|
||||
|
||||
@Column(name = "arrived_at_mailbox_at")
|
||||
var arrivedAtMailboxAt: LocalDateTime? = null,
|
||||
|
||||
@Column(name = "inspection_completed_at")
|
||||
var inspectionCompletedAt: LocalDateTime? = null,
|
||||
|
||||
@Column(name = "delivered_at")
|
||||
var deliveredAt: LocalDateTime? = null,
|
||||
|
||||
@Column(name = "canceled_at")
|
||||
var canceledAt: LocalDateTime? = null,
|
||||
|
||||
@Column(name = "undeliverable_at")
|
||||
var undeliverableAt: LocalDateTime? = null,
|
||||
|
||||
@Column(name = "undeliverable_reason", length = 255)
|
||||
var undeliverableReason: String? = null
|
||||
) : BaseEntity()
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
|
||||
interface GiftDeliveryRepository : JpaRepository<GiftDelivery, Long> {
|
||||
fun findByGiftId(giftId: Long): GiftDelivery?
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence
|
||||
|
||||
import kr.co.vividnext.sodalive.common.BaseEntity
|
||||
import javax.persistence.Column
|
||||
import javax.persistence.Entity
|
||||
import javax.persistence.Table
|
||||
import javax.persistence.UniqueConstraint
|
||||
|
||||
@Entity
|
||||
@Table(
|
||||
name = "gift_review",
|
||||
uniqueConstraints = [UniqueConstraint(name = "uk_gift_review_gift_id", columnNames = ["gift_id"])]
|
||||
)
|
||||
class GiftReview(
|
||||
@Column(name = "gift_id", nullable = false)
|
||||
val giftId: Long,
|
||||
|
||||
@Column(name = "sender_member_id", nullable = false)
|
||||
val senderMemberId: Long,
|
||||
|
||||
@Column(name = "rating", nullable = false)
|
||||
val rating: Int,
|
||||
|
||||
@Column(name = "keywords", columnDefinition = "text")
|
||||
var keywords: String? = null,
|
||||
|
||||
@Column(name = "comment", length = 255)
|
||||
var comment: String? = null
|
||||
) : BaseEntity()
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
|
||||
interface GiftReviewRepository : JpaRepository<GiftReview, Long> {
|
||||
fun findByGiftId(giftId: Long): GiftReview?
|
||||
}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
package kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence
|
||||
|
||||
import kr.co.vividnext.sodalive.configs.QueryDslConfig
|
||||
import kr.co.vividnext.sodalive.v2.gift.domain.GiftSize
|
||||
import kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
|
||||
import org.springframework.context.annotation.Import
|
||||
import org.springframework.dao.DataIntegrityViolationException
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@DataJpaTest(
|
||||
properties = [
|
||||
"spring.cache.type=none",
|
||||
"spring.datasource.url=jdbc:h2:mem:testdb;MODE=MySQL;NON_KEYWORDS=VALUE"
|
||||
]
|
||||
)
|
||||
@Import(QueryDslConfig::class)
|
||||
@DisplayName("선물 엔티티 매핑 테스트")
|
||||
class GiftEntityMappingTest @Autowired constructor(
|
||||
private val giftRepository: GiftRepository,
|
||||
private val giftDeliveryRepository: GiftDeliveryRepository,
|
||||
private val giftCategoryRepository: GiftCategoryRepository,
|
||||
private val giftSizePriceRepository: GiftSizePriceRepository,
|
||||
private val giftReviewRepository: GiftReviewRepository,
|
||||
private val giftApplicationNoSequenceRepository: GiftApplicationNoSequenceRepository
|
||||
) {
|
||||
@Test
|
||||
@DisplayName("선물 엔티티와 배송 정보를 저장하고 조회한다")
|
||||
fun shouldSaveAndFindGiftWithDelivery() {
|
||||
val category = giftCategoryRepository.save(
|
||||
GiftCategory(
|
||||
categoryCode = "DOLL",
|
||||
name = "인형",
|
||||
requiresDamageWaiver = true
|
||||
)
|
||||
)
|
||||
giftSizePriceRepository.save(
|
||||
GiftSizePrice(
|
||||
sizeCode = GiftSize.SMALL,
|
||||
basePriceCan = 100,
|
||||
salePriceCan = 80
|
||||
)
|
||||
)
|
||||
val gift = giftRepository.save(
|
||||
Gift(
|
||||
applicationNo = "G20260929000001",
|
||||
senderMemberId = 1L,
|
||||
recipientMemberId = 2L,
|
||||
status = GiftStatus.RECEIVED,
|
||||
sizeCode = GiftSize.SMALL,
|
||||
categoryId = category.id!!,
|
||||
categoryNameSnapshot = category.name,
|
||||
salePriceCan = 80,
|
||||
canUsageId = 10L,
|
||||
senderTermsAgreed = true,
|
||||
senderPrivacyAgreed = true,
|
||||
senderTermsAgreedAt = LocalDateTime.of(2026, 9, 29, 12, 0),
|
||||
senderPrivacyAgreedAt = LocalDateTime.of(2026, 9, 29, 12, 0),
|
||||
damageWaiverAgreed = true
|
||||
)
|
||||
)
|
||||
|
||||
giftDeliveryRepository.save(
|
||||
GiftDelivery(
|
||||
giftId = gift.id!!,
|
||||
senderName = "홍길동",
|
||||
senderPhoneNumber = "01012345678",
|
||||
senderZipCode = "06234",
|
||||
senderAddress = "서울시 강남구",
|
||||
senderAddressDetail = "101동 1001호",
|
||||
trackingDeadlineAt = LocalDateTime.of(2026, 10, 2, 12, 0)
|
||||
)
|
||||
)
|
||||
|
||||
val saved = giftRepository.findByApplicationNo("G20260929000001")
|
||||
val delivery = giftDeliveryRepository.findByGiftId(gift.id!!)
|
||||
|
||||
assertNotNull(saved)
|
||||
assertEquals(GiftStatus.RECEIVED, saved!!.status)
|
||||
assertEquals("홍길동", delivery!!.senderName)
|
||||
assertNotNull(saved.createdAt)
|
||||
assertNotNull(saved.updatedAt)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("신청번호와 카테고리 코드와 리뷰 선물 ID는 중복 저장할 수 없다")
|
||||
fun shouldRejectDuplicateUniqueValues() {
|
||||
val category = giftCategoryRepository.save(GiftCategory(categoryCode = "DOLL", name = "인형"))
|
||||
val gift = giftRepository.save(gift(category.id!!, "G20260929000001"))
|
||||
giftRepository.saveAndFlush(gift(category.id!!, "G20260929000002"))
|
||||
giftReviewRepository.saveAndFlush(GiftReview(giftId = gift.id!!, senderMemberId = 1L, rating = 5))
|
||||
|
||||
assertThrows(DataIntegrityViolationException::class.java) {
|
||||
giftRepository.saveAndFlush(gift(category.id!!, "G20260929000001"))
|
||||
}
|
||||
assertThrows(DataIntegrityViolationException::class.java) {
|
||||
giftCategoryRepository.saveAndFlush(GiftCategory(categoryCode = "DOLL", name = "중복"))
|
||||
}
|
||||
assertThrows(DataIntegrityViolationException::class.java) {
|
||||
giftReviewRepository.saveAndFlush(GiftReview(giftId = gift.id!!, senderMemberId = 1L, rating = 4))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("날짜별 신청번호 채번 sequence를 저장한다")
|
||||
fun shouldSaveApplicationNoSequence() {
|
||||
val sequence = giftApplicationNoSequenceRepository.save(
|
||||
GiftApplicationNoSequence(sequenceDate = "20260929", lastSequence = 1)
|
||||
)
|
||||
|
||||
assertEquals("20260929", sequence.sequenceDate)
|
||||
assertEquals(1, sequence.lastSequence)
|
||||
}
|
||||
|
||||
private fun gift(categoryId: Long, applicationNo: String) = Gift(
|
||||
applicationNo = applicationNo,
|
||||
senderMemberId = 1L,
|
||||
recipientMemberId = 2L,
|
||||
status = GiftStatus.RECEIVED,
|
||||
sizeCode = GiftSize.SMALL,
|
||||
categoryId = categoryId,
|
||||
categoryNameSnapshot = "인형",
|
||||
salePriceCan = 80,
|
||||
canUsageId = 10L,
|
||||
senderTermsAgreed = true,
|
||||
senderPrivacyAgreed = true,
|
||||
senderTermsAgreedAt = LocalDateTime.of(2026, 9, 29, 12, 0),
|
||||
senderPrivacyAgreedAt = LocalDateTime.of(2026, 9, 29, 12, 0),
|
||||
damageWaiverAgreed = true
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user