Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.doki.productpackage.application
package com.doki.productpackage.pkg.application

import com.doki.productpackage.product.domain.Product
import com.doki.productpackage.product.domain.ProductRepository
import com.doki.productpackage.application.dto.CreatePackageCommand
import com.doki.productpackage.domain.Package
import com.doki.productpackage.infrastructure.PackageCommandRepository
import com.doki.productpackage.pkg.application.dto.CreatePackageCommand
import com.doki.productpackage.pkg.domain.Package
import com.doki.productpackage.pkg.infrastructure.PackageCommandRepository
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.doki.productpackage.application
package com.doki.productpackage.pkg.application

import com.doki.productpackage.domain.PackageRepository
import com.doki.productpackage.domain.dto.PackagePagingQueryResponse
import com.doki.productpackage.domain.dto.PackageSpecificResponse
import com.doki.productpackage.pkg.domain.PackageRepository
import com.doki.productpackage.pkg.domain.dto.PackagePagingQueryResponse
import com.doki.productpackage.pkg.domain.dto.PackageSpecificResponse
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

Expand All @@ -15,8 +15,16 @@ class PackageQueryService(
private val packageRepository: PackageRepository,
) {

fun findPackagesByPaging(): List<PackagePagingQueryResponse> =
packageRepository.findPackagesByPaging()
fun findPackagesByNoOffset(
lastId: Long?,
size: Int,
tagName: String?,
): List<PackagePagingQueryResponse> =
packageRepository.findPackagesByNoOffset(
lastId = lastId,
size = size,
tagName = tagName
)

fun findPackageSpecificById(packageId: Long): PackageSpecificResponse {
return packageRepository.findPackageSpecificById(packageId)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.doki.productpackage.application.dto
package com.doki.productpackage.pkg.application.dto

import java.time.LocalDate

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.doki.productpackage.pkg.application.dto

import io.swagger.v3.oas.annotations.media.Schema

data class PackageCreatedResponse(
@field:Schema(description = "생성된 패키지 ID", example = "1")
val id: Long,
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.doki.productpackage.domain
package com.doki.productpackage.pkg.domain

import com.doki.global.BaseEntity
import com.doki.productpackage.product.domain.Product
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.doki.productpackage.domain
package com.doki.productpackage.pkg.domain

import com.doki.global.BaseEntity
import com.doki.productpackage.product.domain.Product
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.doki.productpackage.pkg.domain

import com.doki.productpackage.pkg.domain.dto.PackagePagingQueryResponse
import com.doki.productpackage.pkg.domain.dto.PackageSpecificResponse

interface PackageRepository {

fun findPackagesByNoOffset(
lastId: Long?,
size: Int,
tagName: String?,
): List<PackagePagingQueryResponse>

fun findPackageSpecificById(packageId: Long): PackageSpecificResponse?

fun findById(packageId: Long): Package?

fun existsById(packageId: Long): Boolean

fun getReferenceById(packageId: Long): Package
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.doki.productpackage.domain
package com.doki.productpackage.pkg.domain

import com.doki.global.BaseEntity
import jakarta.persistence.Column
Expand All @@ -11,12 +11,17 @@ import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne
import jakarta.persistence.Table
import jakarta.persistence.UniqueConstraint
import jakarta.persistence.Index

@Entity
@Table(
name = "package_tag",
uniqueConstraints = [
UniqueConstraint(name = "uk_package_tag", columnNames = ["package_id", "tag_name"])
],
indexes = [
Index(name = "idx_package_tag_tag_name", columnList = "tag_name"),
Index(name = "idx_package_tag_package_id", columnList = "package_id"),
]
)
class PackageTag(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.doki.productpackage.pkg.domain.dto

import com.doki.productpackage.pkg.domain.Package
import io.swagger.v3.oas.annotations.media.Schema
import java.math.BigDecimal

data class PackagePagingQueryResponse(
@field:Schema(description = "패키지 ID", example = "1")
val id: Long,

@field:Schema(description = "패키지명", example = "뷰티 올인원 패키지")
val name: String,

@field:Schema(description = "패키지 설명", example = "머리와 피부 관리 올인원 패키지")
val description: String,

@field:Schema(description = "최저가", example = "100000.00")
val minPrice: BigDecimal,

@field:Schema(description = "총합 가격", example = "300000.00")
val totalPrice: BigDecimal,

@field:Schema(description = "태그 목록", example = "[\"뷰티\",\"헤어\"]")
val tagNames: List<String>,
) {
companion object {
fun from(
pkg: Package,
tagNames: List<String> = pkg.packageTags.map { it.tagName }.distinct(),
): PackagePagingQueryResponse =
PackagePagingQueryResponse(
id = pkg.id,
name = pkg.name,
description = pkg.description,
minPrice = pkg.minPrice,
totalPrice = pkg.totalPrice,
tagNames = tagNames
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.doki.productpackage.pkg.domain.dto

import com.doki.productpackage.pkg.domain.Package
import com.doki.productpackage.product.domain.Product
import io.swagger.v3.oas.annotations.media.Schema
import java.math.BigDecimal
import java.time.LocalDate
import java.time.LocalTime

data class PackageSpecificResponse(
@field:Schema(description = "패키지 ID", example = "1")
val id: Long,

@field:Schema(description = "패키지명", example = "스파 + 디너 패키지")
val name: String,

@field:Schema(description = "패키지 설명", example = "스파 이용권과 디너 코스를 포함합니다.")
val description: String,

@field:Schema(description = "포함 상품 목록")
val products: List<PackageProductResponse>,

@field:Schema(description = "태그 목록", example = "[\"스파\",\"맛집\"]")
val tagNames: List<String>,

@field:Schema(description = "예약 시작 가능 날짜", example = "2025-01-01")
val slotStartDate: LocalDate?,

@field:Schema(description = "예약 마감 날짜", example = "2025-01-07")
val slotEndDate: LocalDate?,

@field:Schema(description = "예약 슬롯 시작 시간", example = "09:00:00")
val slotStartTime: LocalTime?,

@field:Schema(description = "예약 슬롯 종료 시간", example = "16:00:00")
val slotEndTime: LocalTime?,

@field:Schema(description = "예약 슬롯 개수", example = "56")
val reservationSlotCount: Int,

@field:Schema(description = "최저가", example = "100000.00")
val minPrice: BigDecimal,

@field:Schema(description = "총합 가격", example = "300000.00")
val totalPrice: BigDecimal,
) {
companion object {
fun from(pkg: Package): PackageSpecificResponse {
val slotStartDate: LocalDate? = pkg.reservationSlots.minOfOrNull { it.reservationDate }
val slotEndDate: LocalDate? = pkg.reservationSlots.maxOfOrNull { it.reservationDate }
val slotStartTime: LocalTime? = pkg.reservationSlots.minByOrNull { it.startTime }?.startTime
val slotEndTime: LocalTime? = pkg.reservationSlots.maxByOrNull { it.endTime }?.endTime

return PackageSpecificResponse(
id = pkg.id,
name = pkg.name,
description = pkg.description,
products = pkg.packageProducts.map { PackageProductResponse.from(it.product) },
tagNames = pkg.packageTags.map { it.tagName }.distinct(),
slotStartDate = slotStartDate,
slotEndDate = slotEndDate,
slotStartTime = slotStartTime,
slotEndTime = slotEndTime,
reservationSlotCount = pkg.reservationSlots.size,
minPrice = pkg.minPrice,
totalPrice = pkg.totalPrice
)
}
}
}

data class PackageProductResponse(
@field:Schema(description = "상품 ID", example = "1")
val id: Long,

@field:Schema(description = "상품명", example = "스파 이용권")
val name: String,

@field:Schema(description = "상품 설명", example = "프라이빗 스파 2시간 이용")
val description: String,

@field:Schema(description = "가격", example = "100000.00")
val price: BigDecimal,

@field:Schema(description = "장소", example = "서울")
val location: String,
) {
companion object {
fun from(product: Product): PackageProductResponse =
PackageProductResponse(
id = product.id,
name = product.name,
description = product.description,
price = product.price,
location = product.location
)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.doki.productpackage.infrastructure
package com.doki.productpackage.pkg.infrastructure

import com.doki.productpackage.domain.Package
import com.doki.productpackage.pkg.domain.Package
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Repository

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.doki.productpackage.infrastructure
package com.doki.productpackage.pkg.infrastructure

import com.doki.productpackage.domain.Package
import com.doki.productpackage.pkg.domain.Package
import org.springframework.data.jpa.repository.JpaRepository

interface PackageJpaRepository : JpaRepository<Package, Long>
Loading