From 4a2834819f857fd1f07fc2e7113cbf28e7e7607d Mon Sep 17 00:00:00 2001 From: androidlover5842 Date: Sat, 24 Jan 2026 23:07:45 +0530 Subject: [PATCH] pre assign rooms before checkin --- .../controller/BookingFlow.kt | 45 +++++++++++++++++++ .../controller/dto/BookingDtos.kt | 7 +++ .../trisolarisserver/repo/RoomStayRepo.kt | 15 +++++++ 3 files changed, 67 insertions(+) diff --git a/src/main/kotlin/com/android/trisolarisserver/controller/BookingFlow.kt b/src/main/kotlin/com/android/trisolarisserver/controller/BookingFlow.kt index 7ba2804..7ab790f 100644 --- a/src/main/kotlin/com/android/trisolarisserver/controller/BookingFlow.kt +++ b/src/main/kotlin/com/android/trisolarisserver/controller/BookingFlow.kt @@ -5,6 +5,7 @@ import com.android.trisolarisserver.controller.dto.BookingCancelRequest import com.android.trisolarisserver.controller.dto.BookingCheckInRequest import com.android.trisolarisserver.controller.dto.BookingCheckOutRequest import com.android.trisolarisserver.controller.dto.BookingNoShowRequest +import com.android.trisolarisserver.controller.dto.RoomStayPreAssignRequest import com.android.trisolarisserver.db.repo.BookingRepo import com.android.trisolarisserver.models.booking.BookingStatus import com.android.trisolarisserver.models.booking.TransportMode @@ -172,6 +173,50 @@ class BookingFlow( bookingRepo.save(booking) } + @PostMapping("/{bookingId}/room-stays") + @ResponseStatus(HttpStatus.CREATED) + @Transactional + fun preAssignRoom( + @PathVariable propertyId: UUID, + @PathVariable bookingId: UUID, + @AuthenticationPrincipal principal: MyPrincipal?, + @RequestBody request: RoomStayPreAssignRequest + ) { + val actor = requireActor(propertyId, principal) + val booking = requireBooking(propertyId, bookingId) + if (booking.status == BookingStatus.CANCELLED || booking.status == BookingStatus.NO_SHOW || booking.status == BookingStatus.CHECKED_OUT) { + throw ResponseStatusException(HttpStatus.CONFLICT, "Booking closed") + } + + val room = roomRepo.findByIdAndPropertyId(request.roomId, propertyId) + ?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "Room not found") + if (!room.active || room.maintenance) { + throw ResponseStatusException(HttpStatus.CONFLICT, "Room not available") + } + + val fromAt = parseOffset(request.fromAt) + ?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "fromAt required") + val toAt = parseOffset(request.toAt) + ?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "toAt required") + if (!toAt.isAfter(fromAt)) { + throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid date range") + } + + if (roomStayRepo.existsOverlap(propertyId, request.roomId, fromAt, toAt)) { + throw ResponseStatusException(HttpStatus.CONFLICT, "Room already reserved/occupied for range") + } + + val stay = RoomStay( + property = booking.property, + booking = booking, + room = room, + fromAt = fromAt, + toAt = toAt, + createdBy = actor + ) + roomStayRepo.save(stay) + } + private fun requireBooking(propertyId: UUID, bookingId: UUID): com.android.trisolarisserver.models.booking.Booking { val booking = bookingRepo.findById(bookingId).orElseThrow { ResponseStatusException(HttpStatus.NOT_FOUND, "Booking not found") diff --git a/src/main/kotlin/com/android/trisolarisserver/controller/dto/BookingDtos.kt b/src/main/kotlin/com/android/trisolarisserver/controller/dto/BookingDtos.kt index 47968b5..48bb6d1 100644 --- a/src/main/kotlin/com/android/trisolarisserver/controller/dto/BookingDtos.kt +++ b/src/main/kotlin/com/android/trisolarisserver/controller/dto/BookingDtos.kt @@ -38,3 +38,10 @@ data class RoomChangeResponse( val newRoomId: UUID, val movedAt: String ) + +data class RoomStayPreAssignRequest( + val roomId: UUID, + val fromAt: String, + val toAt: String, + val notes: String? = null +) diff --git a/src/main/kotlin/com/android/trisolarisserver/repo/RoomStayRepo.kt b/src/main/kotlin/com/android/trisolarisserver/repo/RoomStayRepo.kt index c35e1f8..e794e27 100644 --- a/src/main/kotlin/com/android/trisolarisserver/repo/RoomStayRepo.kt +++ b/src/main/kotlin/com/android/trisolarisserver/repo/RoomStayRepo.kt @@ -47,4 +47,19 @@ interface RoomStayRepo : JpaRepository { @Param("propertyId") propertyId: UUID, @Param("roomIds") roomIds: List ): List + + @Query(""" + select case when count(rs) > 0 then true else false end + from RoomStay rs + where rs.property.id = :propertyId + and rs.room.id = :roomId + and rs.fromAt < :toAt + and (rs.toAt is null or rs.toAt > :fromAt) + """) + fun existsOverlap( + @Param("propertyId") propertyId: UUID, + @Param("roomId") roomId: UUID, + @Param("fromAt") fromAt: java.time.OffsetDateTime, + @Param("toAt") toAt: java.time.OffsetDateTime + ): Boolean }