diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/persistence/Gift.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/persistence/Gift.kt new file mode 100644 index 00000000..555dffb4 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/persistence/Gift.kt @@ -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() diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/persistence/GiftCategory.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/persistence/GiftCategory.kt new file mode 100644 index 00000000..8974588f --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/persistence/GiftCategory.kt @@ -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() diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/persistence/GiftCategoryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/persistence/GiftCategoryRepository.kt new file mode 100644 index 00000000..7eeae705 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/persistence/GiftCategoryRepository.kt @@ -0,0 +1,7 @@ +package kr.co.vividnext.sodalive.v2.gift.adapter.out.persistence + +import org.springframework.data.jpa.repository.JpaRepository + +interface GiftCategoryRepository : JpaRepository { + fun findByCategoryCode(categoryCode: String): GiftCategory? +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/persistence/GiftRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/persistence/GiftRepository.kt new file mode 100644 index 00000000..1c055939 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/persistence/GiftRepository.kt @@ -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 { + fun findByApplicationNo(applicationNo: String): Gift? + + fun findBySenderMemberId(senderMemberId: Long, pageable: Pageable): Page + + fun findByRecipientMemberIdAndStatusIn( + recipientMemberId: Long, + statuses: Collection, + pageable: Pageable + ): Page + + fun findBySenderMemberIdOrRecipientMemberIdAndStatusIn( + senderMemberId: Long, + recipientMemberId: Long, + statuses: Collection, + pageable: Pageable + ): Page + + @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 + + @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 + + @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 + + @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 +}