[#39] '시간' -> '일정' 스키마 변경으로 테마별 시간 지정 #40

Merged
pricelees merged 16 commits from refactor/#39 into main 2025-09-04 04:14:12 +00:00
4 changed files with 52 additions and 23 deletions
Showing only changes of commit af53ab666f - Show all commits

View File

@ -23,6 +23,16 @@ class ThemeServiceV2(
private val memberService: MemberService, private val memberService: MemberService,
private val themeValidator: ThemeValidatorV2 private val themeValidator: ThemeValidatorV2
) { ) {
@Transactional(readOnly = true)
fun findThemesByIds(request: ThemeListRetrieveRequest): ThemeRetrieveListResponseV2 {
log.info { "[ThemeService.findThemesByIds] 예약 페이지에서의 테마 목록 조회 시작: themeIds=${request.themeIds}" }
return request.themeIds
.map { findOrThrow(it) }
.toRetrieveListResponse()
.also { log.info { "[ThemeService.findThemesByIds] ${it.themes.size}개 테마 조회 완료" } }
}
@Transactional(readOnly = true) @Transactional(readOnly = true)
fun findThemesForReservation(): ThemeRetrieveListResponseV2 { fun findThemesForReservation(): ThemeRetrieveListResponseV2 {
log.info { "[ThemeService.findThemesForReservation] 예약 페이지에서의 테마 목록 조회 시작" } log.info { "[ThemeService.findThemesForReservation] 예약 페이지에서의 테마 목록 조회 시작" }
@ -43,19 +53,15 @@ class ThemeServiceV2(
@Transactional(readOnly = true) @Transactional(readOnly = true)
fun findAdminThemeDetail(id: Long): AdminThemeDetailRetrieveResponse { fun findAdminThemeDetail(id: Long): AdminThemeDetailRetrieveResponse {
log.info { "[ThemeService.findAdminThemeDetail] 관리자 페이지에서의 테마 상세 정보 조회 시작" } log.info { "[ThemeService.findAdminThemeDetail] 관리자 페이지에서의 테마 상세 정보 조회 시작: id=${id}" }
val theme = themeRepository.findByIdOrNull(id) val theme: ThemeEntityV2 = findOrThrow(id)
?: run {
log.warn { "[ThemeService.findAdminThemeDetail] 테마 조회 실패. id=$id" }
throw ThemeException(ThemeErrorCode.THEME_NOT_FOUND)
}
val createdBy = memberService.findById(theme.createdBy).name val createdBy = memberService.findById(theme.createdBy).name
val updatedBy = memberService.findById(theme.updatedBy).name val updatedBy = memberService.findById(theme.updatedBy).name
return theme.toAdminThemeDetailResponse(createdBy, updatedBy) return theme.toAdminThemeDetailResponse(createdBy, updatedBy)
.also { log.info { "[ThemeService.findAdminThemeDetail] 테마 상세 조회 완료. id=$id, name=${theme.name}" } } .also { log.info { "[ThemeService.findAdminThemeDetail] 테마 상세 조회 완료: id=$id, name=${theme.name}" } }
} }
@Transactional @Transactional
@ -69,36 +75,28 @@ class ThemeServiceV2(
) )
return ThemeCreateResponseV2(theme.id).also { return ThemeCreateResponseV2(theme.id).also {
log.info { "[ThemeService.createTheme] 테마 생성 완료. id=${theme.id}, name=${theme.name}" } log.info { "[ThemeService.createTheme] 테마 생성 완료: id=${theme.id}, name=${theme.name}" }
} }
} }
@Transactional @Transactional
fun deleteTheme(id: Long) { fun deleteTheme(id: Long) {
log.info { "[ThemeService.deleteTheme] 테마 삭제 시작" } log.info { "[ThemeService.deleteTheme] 테마 삭제 시작: id=${id}" }
val theme = themeRepository.findByIdOrNull(id) val theme: ThemeEntityV2 = findOrThrow(id)
?: run {
log.warn { "[ThemeService.deleteTheme] 테마 조회 실패. id=$id" }
throw ThemeException(ThemeErrorCode.THEME_NOT_FOUND)
}
themeRepository.delete(theme).also { themeRepository.delete(theme).also {
log.info { "[ThemeService.deleteTheme] 테마 삭제 완료. id=$id, name=${theme.name}" } log.info { "[ThemeService.deleteTheme] 테마 삭제 완료: id=$id, name=${theme.name}" }
} }
} }
@Transactional @Transactional
fun updateTheme(id: Long, request: ThemeUpdateRequest) { fun updateTheme(id: Long, request: ThemeUpdateRequest) {
log.info { "[ThemeService.updateTheme] 테마 수정 시작" } log.info { "[ThemeService.updateTheme] 테마 수정 시작: id=${id}, request=${request}" }
themeValidator.validateCanUpdate(request) themeValidator.validateCanUpdate(request)
val theme: ThemeEntityV2 = themeRepository.findByIdOrNull(id) val theme: ThemeEntityV2 = findOrThrow(id)
?: run {
log.warn { "[ThemeService.updateTheme] 테마 조회 실패. id=$id" }
throw ThemeException(ThemeErrorCode.THEME_NOT_FOUND)
}
theme.modifyIfNotNull( theme.modifyIfNotNull(
request.name, request.name,
@ -112,6 +110,18 @@ class ThemeServiceV2(
request.expectedMinutesFrom, request.expectedMinutesFrom,
request.expectedMinutesTo, request.expectedMinutesTo,
request.isOpen, request.isOpen,
) ).also {
log.info { "[ThemeService.updateTheme] 테마 수정 완료: id=$id, request=${request}" }
}
}
private fun findOrThrow(id: Long): ThemeEntityV2 {
log.info { "[ThemeService.findOrThrow] 테마 조회 시작: id=$id" }
return themeRepository.findByIdOrNull(id)
?: run {
log.warn { "[ThemeService.updateTheme] 테마 조회 실패: id=$id" }
throw ThemeException(ThemeErrorCode.THEME_NOT_FOUND)
}
} }
} }

View File

@ -15,6 +15,7 @@ import roomescape.theme.web.AdminThemeDetailRetrieveResponse
import roomescape.theme.web.AdminThemeSummaryRetrieveListResponse import roomescape.theme.web.AdminThemeSummaryRetrieveListResponse
import roomescape.theme.web.ThemeCreateRequestV2 import roomescape.theme.web.ThemeCreateRequestV2
import roomescape.theme.web.ThemeCreateResponseV2 import roomescape.theme.web.ThemeCreateResponseV2
import roomescape.theme.web.ThemeListRetrieveRequest
import roomescape.theme.web.ThemeUpdateRequest import roomescape.theme.web.ThemeUpdateRequest
import roomescape.theme.web.ThemeRetrieveListResponseV2 import roomescape.theme.web.ThemeRetrieveListResponseV2
@ -33,7 +34,7 @@ interface ThemeAPIV2 {
@Admin @Admin
@Operation(summary = "테마 추가", tags = ["관리자 로그인이 필요한 API"]) @Operation(summary = "테마 추가", tags = ["관리자 로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "201", description = "성공", useReturnTypeSchema = true)) @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
fun createTheme(@Valid @RequestBody themeCreateRequestV2: ThemeCreateRequestV2): ResponseEntity<CommonApiResponse<ThemeCreateResponseV2>> fun createTheme(@Valid @RequestBody themeCreateRequestV2: ThemeCreateRequestV2): ResponseEntity<CommonApiResponse<ThemeCreateResponseV2>>
@Admin @Admin
@ -53,4 +54,9 @@ interface ThemeAPIV2 {
@Operation(summary = "예약 페이지에서 모든 테마 조회", description = "모든 테마를 조회합니다.", tags = ["로그인이 필요한 API"]) @Operation(summary = "예약 페이지에서 모든 테마 조회", description = "모든 테마를 조회합니다.", tags = ["로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
fun findUserThemes(): ResponseEntity<CommonApiResponse<ThemeRetrieveListResponseV2>> fun findUserThemes(): ResponseEntity<CommonApiResponse<ThemeRetrieveListResponseV2>>
@LoginRequired
@Operation(summary = "예약 페이지에서 입력한 날짜에 가능한 테마 조회", description = "입력한 날짜에 가능한 테마를 조회합니다.", tags = ["로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
fun findThemesByIds(request: ThemeListRetrieveRequest): ResponseEntity<CommonApiResponse<ThemeRetrieveListResponseV2>>
} }

View File

@ -12,6 +12,15 @@ class ThemeControllerV2(
private val themeService: ThemeServiceV2, private val themeService: ThemeServiceV2,
) : ThemeAPIV2 { ) : ThemeAPIV2 {
@PostMapping("/themes/retrieve")
override fun findThemesByIds(
@RequestBody request: ThemeListRetrieveRequest
): ResponseEntity<CommonApiResponse<ThemeRetrieveListResponseV2>> {
val response = themeService.findThemesByIds(request)
return ResponseEntity.ok(CommonApiResponse(response))
}
@GetMapping("/v2/themes") @GetMapping("/v2/themes")
override fun findUserThemes(): ResponseEntity<CommonApiResponse<ThemeRetrieveListResponseV2>> { override fun findUserThemes(): ResponseEntity<CommonApiResponse<ThemeRetrieveListResponseV2>> {
val response = themeService.findThemesForReservation() val response = themeService.findThemesForReservation()

View File

@ -114,6 +114,10 @@ fun ThemeEntityV2.toAdminThemeDetailResponse(createUserName: String, updateUserN
updatedBy = updateUserName updatedBy = updateUserName
) )
data class ThemeListRetrieveRequest(
val themeIds: List<Long>
)
data class ThemeRetrieveResponseV2( data class ThemeRetrieveResponseV2(
val id: Long, val id: Long,
val name: String, val name: String,