generated from pricelees/issue-pr-template
[#16] Reservation 도메인 코드 코틀린 마이그레이션 #17
@ -1,103 +1,87 @@
|
|||||||
package roomescape.reservation.business;
|
package roomescape.reservation.business
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import org.springframework.data.repository.findByIdOrNull
|
||||||
import java.util.List;
|
import org.springframework.http.HttpStatus
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.transaction.annotation.Transactional
|
||||||
import org.springframework.stereotype.Service;
|
import roomescape.common.exception.ErrorType
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import roomescape.common.exception.RoomescapeException
|
||||||
|
import roomescape.reservation.infrastructure.persistence.ReservationEntity
|
||||||
import roomescape.common.exception.ErrorType;
|
import roomescape.reservation.infrastructure.persistence.ReservationRepository
|
||||||
import roomescape.common.exception.RoomescapeException;
|
import roomescape.reservation.infrastructure.persistence.ReservationTimeEntity
|
||||||
import roomescape.reservation.infrastructure.persistence.ReservationEntity;
|
import roomescape.reservation.infrastructure.persistence.ReservationTimeRepository
|
||||||
import roomescape.reservation.infrastructure.persistence.ReservationRepository;
|
import roomescape.reservation.web.*
|
||||||
import roomescape.reservation.infrastructure.persistence.ReservationTimeEntity;
|
import java.time.LocalDate
|
||||||
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;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional
|
class ReservationTimeService(
|
||||||
public 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(
|
@Transactional(readOnly = true)
|
||||||
ReservationTimeRepository reservationTimeRepository,
|
fun findAllTimes(): ReservationTimesResponse {
|
||||||
ReservationRepository reservationRepository
|
val response = reservationTimeRepository.findAll()
|
||||||
) {
|
.map { it.toResponse() }
|
||||||
this.reservationTimeRepository = reservationTimeRepository;
|
|
||||||
this.reservationRepository = reservationRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
return ReservationTimesResponse(response)
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional
|
||||||
public ReservationTimesResponse findAllTimes() {
|
fun addTime(reservationTimeRequest: ReservationTimeRequest): ReservationTimeResponse {
|
||||||
List<ReservationTimeResponse> response = reservationTimeRepository.findAll()
|
validateIsDuplicatedTimeExists(reservationTimeRequest)
|
||||||
.stream()
|
|
||||||
.map(ReservationTimeResponse::from)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
return new ReservationTimesResponse(response);
|
return ReservationTimeEntity(startAt = reservationTimeRequest.startAt)
|
||||||
}
|
.also { reservationTimeRepository.save(it) }
|
||||||
|
.toResponse()
|
||||||
|
}
|
||||||
|
|
||||||
public ReservationTimeResponse addTime(ReservationTimeRequest reservationTimeRequest) {
|
private fun validateIsDuplicatedTimeExists(reservationTimeRequest: ReservationTimeRequest) {
|
||||||
validateTimeDuplication(reservationTimeRequest);
|
reservationTimeRepository.findByStartAt(reservationTimeRequest.startAt)
|
||||||
ReservationTimeEntity reservationTime = reservationTimeRepository.save(
|
.also {
|
||||||
new ReservationTimeEntity(null, reservationTimeRequest.startAt)
|
if (it.isNotEmpty()) {
|
||||||
);
|
throw RoomescapeException(
|
||||||
|
ErrorType.TIME_DUPLICATED, "[startAt: $it]", HttpStatus.CONFLICT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ReservationTimeResponse.from(reservationTime);
|
@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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void validateTimeDuplication(ReservationTimeRequest reservationTimeRequest) {
|
@Transactional(readOnly = true)
|
||||||
List<ReservationTimeEntity> duplicateReservationTimes = reservationTimeRepository.findByStartAt(
|
fun findAllAvailableTimesByDateAndTheme(date: LocalDate, themeId: Long): ReservationTimeInfosResponse {
|
||||||
reservationTimeRequest.startAt);
|
val allTimes = reservationTimeRepository.findAll()
|
||||||
|
val reservations: List<ReservationEntity> = reservationRepository.findByThemeId(themeId)
|
||||||
|
|
||||||
if (!duplicateReservationTimes.isEmpty()) {
|
return ReservationTimeInfosResponse(allTimes
|
||||||
throw new RoomescapeException(ErrorType.TIME_DUPLICATED,
|
.map { time ->
|
||||||
String.format("[startAt: %s]", reservationTimeRequest.startAt), HttpStatus.CONFLICT);
|
ReservationTimeInfoResponse(
|
||||||
}
|
time.id!!,
|
||||||
}
|
time.startAt,
|
||||||
|
reservations.any { reservation -> reservation.hasSameDateTime(date, time) }
|
||||||
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
|
@JsonIgnore
|
||||||
fun isSameDateAndTime(date: LocalDate?, time: ReservationTimeEntity): Boolean {
|
fun hasSameDateTime(date: LocalDate?, time: ReservationTimeEntity): Boolean {
|
||||||
return this.date == date && time.startAt == this.reservationTime.startAt
|
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)));
|
new ReservationTimeEntity(null, LocalTime.of(12, 30)));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
Long invalidTimeId = saved.getId() + 1;
|
assert saved.getId() != null;
|
||||||
|
long invalidTimeId = saved.getId() + 1;
|
||||||
|
|
||||||
// when & then
|
// when & then
|
||||||
assertThatThrownBy(() -> reservationTimeService.findTimeById(invalidTimeId))
|
assertThatThrownBy(() -> reservationTimeService.findTimeById(invalidTimeId))
|
||||||
@ -85,6 +86,7 @@ class ReservationTimeServiceTest {
|
|||||||
ReservationStatus.CONFIRMED));
|
ReservationStatus.CONFIRMED));
|
||||||
|
|
||||||
// then
|
// then
|
||||||
|
assert reservationTime.getId() != null;
|
||||||
assertThatThrownBy(() -> reservationTimeService.removeTimeById(reservationTime.getId()))
|
assertThatThrownBy(() -> reservationTimeService.removeTimeById(reservationTime.getId()))
|
||||||
.isInstanceOf(RoomescapeException.class);
|
.isInstanceOf(RoomescapeException.class);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user