feat(gift): 선물 기본 영속 모델을 추가한다

This commit is contained in:
2026-09-30 13:34:53 +09:00
parent f3e6d40a4a
commit 3049184ea2
4 changed files with 214 additions and 0 deletions
@@ -0,0 +1,75 @@
package kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence
import kr.co.vividnext.sodalive.common.BaseEntity
import kr.co.vividnext.sodalive.v2.gift.domain.GiftSize
import kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus
import java.time.LocalDateTime
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.EnumType
import javax.persistence.Enumerated
import javax.persistence.Table
import javax.persistence.UniqueConstraint
@Entity
@Table(
name = "gift",
uniqueConstraints = [UniqueConstraint(name = "uk_gift_application_no", columnNames = ["application_no"])]
)
class Gift(
@Column(name = "application_no", nullable = false, length = 20)
val applicationNo: String,
@Column(name = "sender_member_id", nullable = false)
val senderMemberId: Long,
@Column(name = "recipient_member_id", nullable = false)
val recipientMemberId: Long,
@Enumerated(EnumType.STRING)
@Column(name = "status", nullable = false, length = 30)
var status: GiftStatus,
@Enumerated(EnumType.STRING)
@Column(name = "size_code", nullable = false, length = 20)
val sizeCode: GiftSize,
@Column(name = "category_id", nullable = false)
val categoryId: Long,
@Column(name = "category_name_snapshot", nullable = false, length = 50)
val categoryNameSnapshot: String,
@Column(name = "sale_price_can", nullable = false)
val salePriceCan: Int,
@Column(name = "can_usage_id", nullable = false)
val canUsageId: Long,
@Column(name = "sender_terms_agreed", nullable = false)
val senderTermsAgreed: Boolean,
@Column(name = "sender_privacy_agreed", nullable = false)
val senderPrivacyAgreed: Boolean,
@Column(name = "sender_terms_agreed_at", nullable = false)
val senderTermsAgreedAt: LocalDateTime,
@Column(name = "sender_privacy_agreed_at", nullable = false)
val senderPrivacyAgreedAt: LocalDateTime,
@Column(name = "recipient_terms_agreed", nullable = false)
var recipientTermsAgreed: Boolean = false,
@Column(name = "recipient_privacy_agreed", nullable = false)
var recipientPrivacyAgreed: Boolean = false,
@Column(name = "recipient_terms_agreed_at")
var recipientTermsAgreedAt: LocalDateTime? = null,
@Column(name = "recipient_privacy_agreed_at")
var recipientPrivacyAgreedAt: LocalDateTime? = null,
@Column(name = "damage_waiver_agreed", nullable = false)
val damageWaiverAgreed: Boolean = false
) : BaseEntity()
@@ -0,0 +1,26 @@
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_category",
uniqueConstraints = [UniqueConstraint(name = "uk_gift_category_code", columnNames = ["category_code"])]
)
class GiftCategory(
@Column(name = "category_code", nullable = false, length = 50)
val categoryCode: String,
@Column(name = "name", nullable = false, length = 50)
var name: String,
@Column(name = "requires_damage_waiver", nullable = false)
var requiresDamageWaiver: Boolean = false,
@Column(name = "is_active", nullable = false)
var isActive: Boolean = true
) : BaseEntity()
@@ -0,0 +1,7 @@
package kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence
import org.springframework.data.jpa.repository.JpaRepository
interface GiftCategoryRepository : JpaRepository<GiftCategory, Long> {
fun findByCategoryCode(categoryCode: String): GiftCategory?
}
@@ -0,0 +1,106 @@
package kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence
import kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
import java.time.LocalDateTime
interface GiftRepository : JpaRepository<Gift, Long> {
fun findByApplicationNo(applicationNo: String): Gift?
fun findBySenderMemberId(senderMemberId: Long, pageable: Pageable): Page<Gift>
fun findByRecipientMemberIdAndStatusIn(
recipientMemberId: Long,
statuses: Collection<GiftStatus>,
pageable: Pageable
): Page<Gift>
fun findBySenderMemberIdOrRecipientMemberIdAndStatusIn(
senderMemberId: Long,
recipientMemberId: Long,
statuses: Collection<GiftStatus>,
pageable: Pageable
): Page<Gift>
@Query(
"""
select g
from Gift g
where g.status = kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus.RECEIVED
and exists (
select d.id
from GiftDelivery d
where d.giftId = g.id
and d.trackingDeadlineAt < :now
)
"""
)
fun findReceivedGiftsWithTrackingDeadlineBefore(@Param("now") now: LocalDateTime): List<Gift>
@Query(
"""
select g
from Gift g
where g.status = kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus.TRACKING_REGISTERED
and exists (
select d.id
from GiftDelivery d
where d.giftId = g.id
and d.recipientAddressDeadlineAt < :now
and d.recipientAddress is null
)
"""
)
fun findTrackingRegisteredGiftsWithRecipientAddressDeadlineBefore(
@Param("now") now: LocalDateTime
): List<Gift>
@Query(
"""
select g
from Gift g
where g.status = kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus.RECEIVED
and exists (
select d.id
from GiftDelivery d
where d.giftId = g.id
and d.trackingDeadlineAt > :now
and d.trackingDeadlineAt <= :reminderUntil
and d.trackingDeadlineReminderSentAt is null
)
"""
)
fun findReceivedGiftsWithTrackingDeadlineReminderDue(
@Param("now") now: LocalDateTime,
@Param("reminderUntil") reminderUntil: LocalDateTime
): List<Gift>
@Query(
"""
select g
from Gift g
where g.status in (
kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus.TRACKING_REGISTERED,
kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus.ARRIVED_AT_MAILBOX,
kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus.INSPECTION_COMPLETED
)
and exists (
select d.id
from GiftDelivery d
where d.giftId = g.id
and d.recipientAddressDeadlineAt > :now
and d.recipientAddressDeadlineAt <= :reminderUntil
and d.recipientAddress is null
and d.recipientAddressDeadlineReminderSentAt is null
)
"""
)
fun findGiftsWithRecipientAddressDeadlineReminderDue(
@Param("now") now: LocalDateTime,
@Param("reminderUntil") reminderUntil: LocalDateTime
): List<Gift>
}