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

Merged
pricelees merged 16 commits from refactor/#39 into main 2025-09-04 04:14:12 +00:00
3 changed files with 205 additions and 0 deletions
Showing only changes of commit 525b693eff - Show all commits

View File

@ -0,0 +1,69 @@
package roomescape.schedule.docs
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import jakarta.validation.Valid
import org.springframework.format.annotation.DateTimeFormat
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestParam
import roomescape.auth.web.support.Admin
import roomescape.auth.web.support.LoginRequired
import roomescape.common.dto.response.CommonApiResponse
import roomescape.schedule.web.*
import java.time.LocalDate
interface ScheduleAPI {
@LoginRequired
@Operation(summary = "입력된 날짜에 가능한 테마 목록 조회", tags = ["로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "200", description = "입력된 날짜에 가능한 테마 목록 조회", useReturnTypeSchema = true))
fun findAvailableThemes(
@RequestParam("date") @DateTimeFormat(pattern = "yyyy-MM-dd") date: LocalDate
): ResponseEntity<CommonApiResponse<AvailableThemeIdListResponse>>
@LoginRequired
@Operation(summary = "입력된 날짜, 테마에 대한 모든 시간 조회", tags = ["로그인이 필요한 API"])
@ApiResponses(
ApiResponse(
responseCode = "200",
description = "입력된 날짜, 테마에 대한 모든 시간 조회",
useReturnTypeSchema = true
)
)
fun findAllTime(
@RequestParam("date") @DateTimeFormat(pattern = "yyyy-MM-dd") date: LocalDate,
@RequestParam("themeId") themeId: Long
): ResponseEntity<CommonApiResponse<ScheduleRetrieveListResponse>>
@Admin
@Operation(summary = "일정 상세 조회", tags = ["관리자 로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "200", description = "감사 정보를 포함하여 일정 상세 조회", useReturnTypeSchema = true))
fun findScheduleDetail(
@PathVariable("id") id: Long
): ResponseEntity<CommonApiResponse<ScheduleDetailRetrieveResponse>>
@Admin
@Operation(summary = "일정 생성", tags = ["관리자 로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
fun createSchedule(
@Valid @RequestBody request: ScheduleCreateRequest
): ResponseEntity<CommonApiResponse<ScheduleCreateResponse>>
@Admin
@Operation(summary = "일정 수정", tags = ["관리자 로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
fun updateSchedule(
@PathVariable("id") id: Long,
@Valid @RequestBody request: ScheduleUpdateRequest
): ResponseEntity<CommonApiResponse<Unit>>
@Admin
@Operation(summary = "일정 삭제", tags = ["관리자 로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "204", description = "성공", useReturnTypeSchema = true))
fun deleteSchedule(
@PathVariable("id") id: Long
): ResponseEntity<CommonApiResponse<Unit>>
}

View File

@ -0,0 +1,71 @@
package roomescape.schedule.web
import jakarta.validation.Valid
import org.springframework.format.annotation.DateTimeFormat
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import roomescape.common.dto.response.CommonApiResponse
import roomescape.schedule.business.ScheduleService
import roomescape.schedule.docs.ScheduleAPI
import java.time.LocalDate
@RestController
class ScheduleController(
private val scheduleService: ScheduleService
) : ScheduleAPI {
@GetMapping("/schedules/themes")
override fun findAvailableThemes(
@RequestParam("date") @DateTimeFormat(pattern = "yyyy-MM-dd") date: LocalDate
): ResponseEntity<CommonApiResponse<AvailableThemeIdListResponse>> {
val response = scheduleService.findThemesByDate(date)
return ResponseEntity.ok(CommonApiResponse(response))
}
@GetMapping("/schedules")
override fun findAllTime(
@RequestParam("date") @DateTimeFormat(pattern = "yyyy-MM-dd") date: LocalDate,
@RequestParam("themeId") themeId: Long
): ResponseEntity<CommonApiResponse<ScheduleRetrieveListResponse>> {
val response = scheduleService.findSchedules(date, themeId)
return ResponseEntity.ok(CommonApiResponse(response))
}
@GetMapping("/schedules/{id}")
override fun findScheduleDetail(
@PathVariable("id") id: Long
): ResponseEntity<CommonApiResponse<ScheduleDetailRetrieveResponse>> {
val response = scheduleService.findDetail(id)
return ResponseEntity.ok(CommonApiResponse(response))
}
@PostMapping("/schedules")
override fun createSchedule(
@Valid @RequestBody request: ScheduleCreateRequest
): ResponseEntity<CommonApiResponse<ScheduleCreateResponse>> {
val response = scheduleService.createSchedule(request)
return ResponseEntity.ok(CommonApiResponse(response))
}
@PatchMapping("/schedules/{id}")
override fun updateSchedule(
@PathVariable("id") id: Long,
@Valid @RequestBody request: ScheduleUpdateRequest
): ResponseEntity<CommonApiResponse<Unit>> {
scheduleService.updateSchedule(id, request)
return ResponseEntity.ok(CommonApiResponse(Unit))
}
@DeleteMapping("/schedules/{id}")
override fun deleteSchedule(
@PathVariable("id") id: Long
): ResponseEntity<CommonApiResponse<Unit>> {
scheduleService.deleteSchedule(id)
return ResponseEntity.noContent().build()
}
}

View File

@ -0,0 +1,65 @@
package roomescape.schedule.web
import roomescape.schedule.infrastructure.persistence.ScheduleEntity
import roomescape.schedule.infrastructure.persistence.ScheduleStatus
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
data class AvailableThemeIdListResponse(
val themeIds: List<Long>
)
fun List<ScheduleEntity>.toThemeIdListResponse() = AvailableThemeIdListResponse(this.map { it.themeId })
data class ScheduleRetrieveResponse(
val id: Long,
val time: LocalTime,
val status: ScheduleStatus
)
data class ScheduleRetrieveListResponse(
val schedules: List<ScheduleRetrieveResponse>
)
fun List<ScheduleEntity>.toRetrieveListResponse() = ScheduleRetrieveListResponse(
this.map { ScheduleRetrieveResponse(it.id, it.time, it.status) }
)
data class ScheduleCreateRequest(
val date: LocalDate,
val time: LocalTime,
val themeId: Long
)
data class ScheduleCreateResponse(
val id: Long
)
data class ScheduleUpdateRequest(
val time: LocalTime? = null,
val status: ScheduleStatus? = null
)
data class ScheduleDetailRetrieveResponse(
val id: Long,
val date: LocalDate,
val time: LocalTime,
val status: ScheduleStatus,
val createdAt: LocalDateTime,
val createdBy: String,
val updatedAt: LocalDateTime,
val updatedBy: String,
)
fun ScheduleEntity.toDetailRetrieveResponse(createdBy: String, updatedBy: String) = ScheduleDetailRetrieveResponse(
id = this.id,
date = this.date,
time = this.time,
status = this.status,
createdAt = this.createdAt,
createdBy = createdBy,
updatedAt = this.updatedAt,
updatedBy = updatedBy
)