refactor: 테마 / 일정 수정 로직 개선( -> null 필드이면 즉시 중단) 및 로그 메시지 형식 개선

This commit is contained in:
이상진 2025-09-04 12:58:49 +09:00
parent 5122194fc6
commit bf8a005096
6 changed files with 42 additions and 13 deletions

View File

@ -33,7 +33,7 @@ class ScheduleService(
return scheduleRepository.findAllByDate(date) return scheduleRepository.findAllByDate(date)
.toThemeIdListResponse() .toThemeIdListResponse()
.also { .also {
log.info { "[ScheduleService.findThemesByDate] date=${date}${it.themeIds.size}개 테마 조회 완료" } log.info { "[ScheduleService.findThemesByDate] date=${date} ${it.themeIds.size}개 테마 조회 완료" }
} }
} }
@ -44,7 +44,7 @@ class ScheduleService(
return scheduleRepository.findAllByDateAndThemeId(date, themeId) return scheduleRepository.findAllByDateAndThemeId(date, themeId)
.toRetrieveListResponse() .toRetrieveListResponse()
.also { .also {
log.info { "[ScheduleService.findSchedules] date=${date}, themeId=${themeId}${it.schedules.size}개 일정 조회 완료" } log.info { "[ScheduleService.findSchedules] date=${date}, themeId=${themeId} ${it.schedules.size}개 일정 조회 완료" }
} }
} }
@ -86,6 +86,12 @@ class ScheduleService(
@Transactional @Transactional
fun updateSchedule(id: Long, request: ScheduleUpdateRequest) { fun updateSchedule(id: Long, request: ScheduleUpdateRequest) {
log.info { "[ScheduleService.updateSchedule] 일정 수정 시작: id=$id, request=${request}" } log.info { "[ScheduleService.updateSchedule] 일정 수정 시작: id=$id, request=${request}" }
if (request.isAllParamsNull()) {
log.info { "[ScheduleService.updateSchedule] 일정 변경 사항 없음: id=$id" }
return
}
val schedule: ScheduleEntity = findOrThrow(id) val schedule: ScheduleEntity = findOrThrow(id)
scheduleValidator.validateCanUpdate(schedule, request) scheduleValidator.validateCanUpdate(schedule, request)

View File

@ -48,7 +48,7 @@ class ScheduleValidator(
private fun validateAlreadyExists(date: LocalDate, themeId: Long, time: LocalTime) { private fun validateAlreadyExists(date: LocalDate, themeId: Long, time: LocalTime) {
if (scheduleRepository.existsByDateAndThemeIdAndTime(date, themeId, time)) { if (scheduleRepository.existsByDateAndThemeIdAndTime(date, themeId, time)) {
log.info { log.info {
"[ScheduleValidator.validateAlreadyExists] 동일한 날짜, 테마, 시간 존재: date=${date} / themeId=${themeId} / time=${time}" "[ScheduleValidator.validateAlreadyExists] 동일한 날짜, 테마, 시간 존재로 인한 실패: date=${date} / themeId=${themeId} / time=${time}"
} }
throw ScheduleException(ScheduleErrorCode.SCHEDULE_ALREADY_EXISTS) throw ScheduleException(ScheduleErrorCode.SCHEDULE_ALREADY_EXISTS)
} }
@ -59,7 +59,7 @@ class ScheduleValidator(
if (dateTime.isBefore(LocalDateTime.now())) { if (dateTime.isBefore(LocalDateTime.now())) {
log.info { log.info {
"[ScheduleValidator.validateDateTime] 이전 시간 선택: date=${date} / time=${time}" "[ScheduleValidator.validateDateTime] 이전 시간 선택으로 인한 실패: date=${date} / time=${time}"
} }
throw ScheduleException(ScheduleErrorCode.PAST_DATE_TIME) throw ScheduleException(ScheduleErrorCode.PAST_DATE_TIME)
} }

View File

@ -39,7 +39,11 @@ data class ScheduleCreateResponse(
data class ScheduleUpdateRequest( data class ScheduleUpdateRequest(
val time: LocalTime? = null, val time: LocalTime? = null,
val status: ScheduleStatus? = null val status: ScheduleStatus? = null
) ) {
fun isAllParamsNull(): Boolean {
return time == null && status == null
}
}
data class ScheduleDetailRetrieveResponse( data class ScheduleDetailRetrieveResponse(
val id: Long, val id: Long,

View File

@ -94,6 +94,11 @@ class ThemeServiceV2(
fun updateTheme(id: Long, request: ThemeUpdateRequest) { fun updateTheme(id: Long, request: ThemeUpdateRequest) {
log.info { "[ThemeService.updateTheme] 테마 수정 시작: id=${id}, request=${request}" } log.info { "[ThemeService.updateTheme] 테마 수정 시작: id=${id}, request=${request}" }
if (request.isAllParamsNull()) {
log.info { "[ThemeService.updateTheme] 테마 변경 사항 없음: id=${id}" }
return
}
themeValidator.validateCanUpdate(request) themeValidator.validateCanUpdate(request)
val theme: ThemeEntityV2 = findOrThrow(id) val theme: ThemeEntityV2 = findOrThrow(id)

View File

@ -32,7 +32,7 @@ class ThemeValidatorV2(
fun validateCanCreate(request: ThemeCreateRequestV2) { fun validateCanCreate(request: ThemeCreateRequestV2) {
if (themeRepository.existsByName(request.name)) { if (themeRepository.existsByName(request.name)) {
log.info { "[ThemeValidator.validateCanCreate] 이름 중복: name=${request.name}" } log.info { "[ThemeValidator.validateCanCreate] 이름 중복으로 인한 실패: name=${request.name}" }
throw ThemeException(ThemeErrorCode.THEME_NAME_DUPLICATED) throw ThemeException(ThemeErrorCode.THEME_NAME_DUPLICATED)
} }
@ -55,7 +55,7 @@ class ThemeValidatorV2(
maxParticipants: Short?, maxParticipants: Short?,
) { ) {
if (isNotNullAndBelowThan(price, MIN_PRICE)) { if (isNotNullAndBelowThan(price, MIN_PRICE)) {
log.info { "[ThemeValidator.validateCanCreate] 최소 가격 미달: price=${price}" } log.info { "[ThemeValidator.validateCanCreate] 최소 가격 미달로 인한 실패로 인한 실패: price=${price}" }
throw ThemeException(ThemeErrorCode.PRICE_BELOW_MINIMUM) throw ThemeException(ThemeErrorCode.PRICE_BELOW_MINIMUM)
} }
validateTimes(availableMinutes, expectedMinutesFrom, expectedMinutesTo) validateTimes(availableMinutes, expectedMinutesFrom, expectedMinutesTo)
@ -72,18 +72,18 @@ class ThemeValidatorV2(
|| isNotNullAndBelowThan(expectedMinutesTo, MIN_DURATION) || isNotNullAndBelowThan(expectedMinutesTo, MIN_DURATION)
) { ) {
log.info { log.info {
"[ThemeValidator.validateTimes] 최소 시간 미달: availableMinutes=$availableMinutes" + "[ThemeValidator.validateTimes] 최소 시간 미달로 인한 실패로 인한 실패: availableMinutes=$availableMinutes" +
", expectedMinutesFrom=$expectedMinutesFrom, expectedMinutesTo=$expectedMinutesTo" ", expectedMinutesFrom=$expectedMinutesFrom, expectedMinutesTo=$expectedMinutesTo"
} }
throw ThemeException(ThemeErrorCode.DURATION_BELOW_MINIMUM) throw ThemeException(ThemeErrorCode.DURATION_BELOW_MINIMUM)
} }
if (expectedMinutesFrom.isNotNullAndGraterThan(expectedMinutesTo)) { if (expectedMinutesFrom.isNotNullAndGraterThan(expectedMinutesTo)) {
log.info { "[ThemeValidator.validateTimes] 최소 예상 시간의 최대 예상 시간 초과: expectedMinutesFrom=$expectedMinutesFrom, expectedMinutesTo=$expectedMinutesTo" } log.info { "[ThemeValidator.validateTimes] 최소 예상 시간의 최대 예상 시간 초과로 인한 실패: expectedMinutesFrom=$expectedMinutesFrom, expectedMinutesTo=$expectedMinutesTo" }
throw ThemeException(ThemeErrorCode.MIN_EXPECTED_TIME_EXCEEDS_MAX_EXPECTED_TIME) throw ThemeException(ThemeErrorCode.MIN_EXPECTED_TIME_EXCEEDS_MAX_EXPECTED_TIME)
} }
if (expectedMinutesTo.isNotNullAndGraterThan(availableMinutes)) { if (expectedMinutesTo.isNotNullAndGraterThan(availableMinutes)) {
log.info { "[ThemeValidator.validateTimes] 예상 시간의 이용 가능 시간 초과: availableMinutes=$expectedMinutesFrom, expectedMinutesFrom=$expectedMinutesFrom, expectedMinutesTo=$expectedMinutesTo" } log.info { "[ThemeValidator.validateTimes] 예상 시간의 이용 가능 시간 초과로 인한 실패: availableMinutes=$expectedMinutesFrom, expectedMinutesFrom=$expectedMinutesFrom, expectedMinutesTo=$expectedMinutesTo" }
throw ThemeException(ThemeErrorCode.EXPECTED_TIME_EXCEEDS_AVAILABLE_TIME) throw ThemeException(ThemeErrorCode.EXPECTED_TIME_EXCEEDS_AVAILABLE_TIME)
} }
} }
@ -95,11 +95,11 @@ class ThemeValidatorV2(
if (isNotNullAndBelowThan(minParticipants, MIN_PARTICIPANTS) if (isNotNullAndBelowThan(minParticipants, MIN_PARTICIPANTS)
|| isNotNullAndBelowThan(maxParticipants, MIN_PARTICIPANTS) || isNotNullAndBelowThan(maxParticipants, MIN_PARTICIPANTS)
) { ) {
log.info { "[ThemeValidator.validateParticipants] 최소 인원 미달: minParticipants=$minParticipants, maxParticipants=$maxParticipants" } log.info { "[ThemeValidator.validateParticipants] 최소 인원 미달로 인한 실패: minParticipants=$minParticipants, maxParticipants=$maxParticipants" }
throw ThemeException(ThemeErrorCode.PARTICIPANT_BELOW_MINIMUM) throw ThemeException(ThemeErrorCode.PARTICIPANT_BELOW_MINIMUM)
} }
if (minParticipants.isNotNullAndGraterThan(maxParticipants)) { if (minParticipants.isNotNullAndGraterThan(maxParticipants)) {
log.info { "[ThemeValidator.validateParticipants] 최소 인원의 최대 인원 초과: minParticipants=$minParticipants, maxParticipants=$maxParticipants" } log.info { "[ThemeValidator.validateParticipants] 최소 인원의 최대 인원 초과로 인한 실패: minParticipants=$minParticipants, maxParticipants=$maxParticipants" }
throw ThemeException(ThemeErrorCode.MIN_PARTICIPANT_EXCEEDS_MAX_PARTICIPANT) throw ThemeException(ThemeErrorCode.MIN_PARTICIPANT_EXCEEDS_MAX_PARTICIPANT)
} }
} }

View File

@ -49,7 +49,21 @@ data class ThemeUpdateRequest(
val expectedMinutesFrom: Short? = null, val expectedMinutesFrom: Short? = null,
val expectedMinutesTo: Short? = null, val expectedMinutesTo: Short? = null,
val isOpen: Boolean? = null, val isOpen: Boolean? = null,
) ) {
fun isAllParamsNull(): Boolean {
return name == null &&
description == null &&
thumbnailUrl == null &&
difficulty == null &&
price == null &&
minParticipants == null &&
maxParticipants == null &&
availableMinutes == null &&
expectedMinutesFrom == null &&
expectedMinutesTo == null &&
isOpen == null
}
}
data class AdminThemeSummaryRetrieveResponse( data class AdminThemeSummaryRetrieveResponse(
val id: Long, val id: Long,