generated from pricelees/issue-pr-template
refactor: ReservationTimeService 코틀린 전환
This commit is contained in:
parent
d89e662d23
commit
b0290e65ff
@ -1,103 +1,87 @@
|
||||
package roomescape.reservation.business;
|
||||
package roomescape.reservation.business
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import roomescape.common.exception.ErrorType;
|
||||
import roomescape.common.exception.RoomescapeException;
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationEntity;
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationRepository;
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationTimeEntity;
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationTimeRepository;
|
||||
import roomescape.reservation.web.ReservationTimeInfoResponse;
|
||||
import roomescape.reservation.web.ReservationTimeInfosResponse;
|
||||
import roomescape.reservation.web.ReservationTimeRequest;
|
||||
import roomescape.reservation.web.ReservationTimeResponse;
|
||||
import roomescape.reservation.web.ReservationTimesResponse;
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import roomescape.common.exception.ErrorType
|
||||
import roomescape.common.exception.RoomescapeException
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationEntity
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationRepository
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationTimeEntity
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationTimeRepository
|
||||
import roomescape.reservation.web.*
|
||||
import java.time.LocalDate
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
public class ReservationTimeService {
|
||||
class ReservationTimeService(
|
||||
private val reservationTimeRepository: ReservationTimeRepository,
|
||||
private val reservationRepository: ReservationRepository
|
||||
) {
|
||||
@Transactional(readOnly = true)
|
||||
fun findTimeById(id: Long): ReservationTimeEntity = reservationTimeRepository.findByIdOrNull(id)
|
||||
?: throw RoomescapeException(
|
||||
ErrorType.RESERVATION_TIME_NOT_FOUND,
|
||||
"[reservationTimeId: $id]",
|
||||
HttpStatus.BAD_REQUEST
|
||||
)
|
||||
|
||||
private final ReservationTimeRepository reservationTimeRepository;
|
||||
private final ReservationRepository reservationRepository;
|
||||
|
||||
public ReservationTimeService(
|
||||
ReservationTimeRepository reservationTimeRepository,
|
||||
ReservationRepository reservationRepository
|
||||
) {
|
||||
this.reservationTimeRepository = reservationTimeRepository;
|
||||
this.reservationRepository = reservationRepository;
|
||||
@Transactional(readOnly = true)
|
||||
fun findAllTimes(): ReservationTimesResponse {
|
||||
val response = reservationTimeRepository.findAll()
|
||||
.map { it.toResponse() }
|
||||
|
||||
return ReservationTimesResponse(response)
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun addTime(reservationTimeRequest: ReservationTimeRequest): ReservationTimeResponse {
|
||||
validateIsDuplicatedTimeExists(reservationTimeRequest)
|
||||
|
||||
return ReservationTimeEntity(startAt = reservationTimeRequest.startAt)
|
||||
.also { reservationTimeRepository.save(it) }
|
||||
.toResponse()
|
||||
}
|
||||
|
||||
private fun validateIsDuplicatedTimeExists(reservationTimeRequest: ReservationTimeRequest) {
|
||||
reservationTimeRepository.findByStartAt(reservationTimeRequest.startAt)
|
||||
.also {
|
||||
if (it.isNotEmpty()) {
|
||||
throw RoomescapeException(
|
||||
ErrorType.TIME_DUPLICATED, "[startAt: $it]", HttpStatus.CONFLICT
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun removeTimeById(id: Long) {
|
||||
val reservationTime: ReservationTimeEntity = findTimeById(id)
|
||||
reservationRepository.findByReservationTime(reservationTime)
|
||||
.also {
|
||||
if (it.isNotEmpty()) {
|
||||
throw RoomescapeException(
|
||||
ErrorType.TIME_IS_USED_CONFLICT, "[timeId: $id]", HttpStatus.CONFLICT
|
||||
)
|
||||
}
|
||||
reservationTimeRepository.deleteById(id)
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public ReservationTimeEntity findTimeById(Long id) {
|
||||
return reservationTimeRepository.findById(id)
|
||||
.orElseThrow(() -> new RoomescapeException(ErrorType.RESERVATION_TIME_NOT_FOUND,
|
||||
String.format("[reservationTimeId: %d]", id), HttpStatus.BAD_REQUEST));
|
||||
fun findAllAvailableTimesByDateAndTheme(date: LocalDate, themeId: Long): ReservationTimeInfosResponse {
|
||||
val allTimes = reservationTimeRepository.findAll()
|
||||
val reservations: List<ReservationEntity> = reservationRepository.findByThemeId(themeId)
|
||||
|
||||
return ReservationTimeInfosResponse(allTimes
|
||||
.map { time ->
|
||||
ReservationTimeInfoResponse(
|
||||
time.id!!,
|
||||
time.startAt,
|
||||
reservations.any { reservation -> reservation.hasSameDateTime(date, time) }
|
||||
)
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public ReservationTimesResponse findAllTimes() {
|
||||
List<ReservationTimeResponse> response = reservationTimeRepository.findAll()
|
||||
.stream()
|
||||
.map(ReservationTimeResponse::from)
|
||||
.toList();
|
||||
|
||||
return new ReservationTimesResponse(response);
|
||||
}
|
||||
|
||||
public ReservationTimeResponse addTime(ReservationTimeRequest reservationTimeRequest) {
|
||||
validateTimeDuplication(reservationTimeRequest);
|
||||
ReservationTimeEntity reservationTime = reservationTimeRepository.save(
|
||||
new ReservationTimeEntity(null, reservationTimeRequest.startAt)
|
||||
);
|
||||
|
||||
return ReservationTimeResponse.from(reservationTime);
|
||||
}
|
||||
|
||||
private void validateTimeDuplication(ReservationTimeRequest reservationTimeRequest) {
|
||||
List<ReservationTimeEntity> duplicateReservationTimes = reservationTimeRepository.findByStartAt(
|
||||
reservationTimeRequest.startAt);
|
||||
|
||||
if (!duplicateReservationTimes.isEmpty()) {
|
||||
throw new RoomescapeException(ErrorType.TIME_DUPLICATED,
|
||||
String.format("[startAt: %s]", reservationTimeRequest.startAt), HttpStatus.CONFLICT);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeTimeById(Long id) {
|
||||
ReservationTimeEntity reservationTime = findTimeById(id);
|
||||
List<ReservationEntity> usingTimeReservations = reservationRepository.findByReservationTime(reservationTime);
|
||||
|
||||
if (!usingTimeReservations.isEmpty()) {
|
||||
throw new RoomescapeException(ErrorType.TIME_IS_USED_CONFLICT, String.format("[timeId: %d]", id),
|
||||
HttpStatus.CONFLICT);
|
||||
}
|
||||
|
||||
reservationTimeRepository.deleteById(id);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public ReservationTimeInfosResponse findAllAvailableTimesByDateAndTheme(LocalDate date, Long themeId) {
|
||||
List<ReservationTimeEntity> allTimes = reservationTimeRepository.findAll();
|
||||
List<ReservationEntity> reservations = reservationRepository.findByThemeId(themeId);
|
||||
|
||||
List<ReservationTimeInfoResponse> response = allTimes.stream()
|
||||
.map(time -> new ReservationTimeInfoResponse(time.getId(), time.getStartAt(),
|
||||
isReservationBooked(reservations, date, time)))
|
||||
.toList();
|
||||
|
||||
return new ReservationTimeInfosResponse(response);
|
||||
}
|
||||
|
||||
private boolean isReservationBooked(List<ReservationEntity> reservations, LocalDate date,
|
||||
ReservationTimeEntity time) {
|
||||
return reservations.stream()
|
||||
.anyMatch(reservation -> reservation.isSameDateAndTime(date, time));
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ class ReservationEntity(
|
||||
) {
|
||||
|
||||
@JsonIgnore
|
||||
fun isSameDateAndTime(date: LocalDate?, time: ReservationTimeEntity): Boolean {
|
||||
fun hasSameDateTime(date: LocalDate?, time: ReservationTimeEntity): Boolean {
|
||||
return this.date == date && time.startAt == this.reservationTime.startAt
|
||||
}
|
||||
|
||||
|
||||
@ -111,3 +111,7 @@ data class ReservationTimeResponse(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ReservationTimeEntity.toResponse(): ReservationTimeResponse = ReservationTimeResponse(
|
||||
this.id!!, this.startAt
|
||||
)
|
||||
|
||||
@ -61,7 +61,8 @@ class ReservationTimeServiceTest {
|
||||
new ReservationTimeEntity(null, LocalTime.of(12, 30)));
|
||||
|
||||
// when
|
||||
Long invalidTimeId = saved.getId() + 1;
|
||||
assert saved.getId() != null;
|
||||
long invalidTimeId = saved.getId() + 1;
|
||||
|
||||
// when & then
|
||||
assertThatThrownBy(() -> reservationTimeService.findTimeById(invalidTimeId))
|
||||
@ -85,6 +86,7 @@ class ReservationTimeServiceTest {
|
||||
ReservationStatus.CONFIRMED));
|
||||
|
||||
// then
|
||||
assert reservationTime.getId() != null;
|
||||
assertThatThrownBy(() -> reservationTimeService.removeTimeById(reservationTime.getId()))
|
||||
.isInstanceOf(RoomescapeException.class);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user