Files
TrisolarisServer/src/main/kotlin/com/android/trisolarisserver/repo/room/RoomStayRepo.kt
androidlover5842 2950af3332
All checks were successful
build-and-deploy / build-deploy (push) Successful in 37s
Add forecast occupancy logic for room availability range APIs
2026-02-04 17:22:28 +05:30

203 lines
6.0 KiB
Kotlin

package com.android.trisolarisserver.repo.room
import com.android.trisolarisserver.models.room.RoomStay
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
import java.util.UUID
interface RoomStayRepo : JpaRepository<RoomStay, UUID> {
@Query("""
select rs.room.id
from RoomStay rs
where rs.property.id = :propertyId
and rs.toAt is null
and rs.isVoided = false
""")
fun findOccupiedRoomIds(@Param("propertyId") propertyId: UUID): List<UUID>
@Query("""
select distinct rs.room.id
from RoomStay rs
where rs.property.id = :propertyId
and rs.isVoided = false
and rs.fromAt < :toAt
and (rs.toAt is null or rs.toAt > :fromAt)
""")
fun findOccupiedRoomIdsBetween(
@Param("propertyId") propertyId: UUID,
@Param("fromAt") fromAt: java.time.OffsetDateTime,
@Param("toAt") toAt: java.time.OffsetDateTime
): List<UUID>
@Query("""
select distinct rs.room.id
from RoomStay rs
where rs.property.id = :propertyId
and rs.isVoided = false
and rs.toAt is not null
and rs.fromAt < :toAt
and rs.toAt > :fromAt
""")
fun findOccupiedRoomIdsBetweenClosed(
@Param("propertyId") propertyId: UUID,
@Param("fromAt") fromAt: java.time.OffsetDateTime,
@Param("toAt") toAt: java.time.OffsetDateTime
): List<UUID>
@Query("""
select rs.room.id as roomId,
rs.fromAt as fromAt,
b.expectedCheckoutAt as expectedCheckoutAt
from RoomStay rs
join rs.booking b
where rs.property.id = :propertyId
and rs.isVoided = false
and rs.toAt is null
and rs.fromAt < :toAt
""")
fun findActiveForecastRows(
@Param("propertyId") propertyId: UUID,
@Param("toAt") toAt: java.time.OffsetDateTime
): List<ActiveRoomStayForecastRow>
@Query("""
select rs
from RoomStay rs
where rs.booking.id = :bookingId
and rs.toAt is null
and rs.isVoided = false
""")
fun findActiveByBookingId(@Param("bookingId") bookingId: UUID): List<RoomStay>
@Query("""
select rs
from RoomStay rs
where rs.booking.id = :bookingId
and rs.isVoided = false
""")
fun findByBookingId(@Param("bookingId") bookingId: UUID): List<RoomStay>
@Query("""
select rs
from RoomStay rs
join fetch rs.room r
where rs.booking.id = :bookingId
and rs.isVoided = false
""")
fun findByBookingIdWithRoom(@Param("bookingId") bookingId: UUID): List<RoomStay>
@Query("""
select rs
from RoomStay rs
where rs.booking.id in :bookingIds
and rs.isVoided = false
""")
fun findByBookingIdIn(@Param("bookingIds") bookingIds: List<UUID>): List<RoomStay>
@Query("""
select rs.room.id
from RoomStay rs
where rs.property.id = :propertyId
and rs.room.id in :roomIds
and rs.toAt is null
and rs.isVoided = false
""")
fun findActiveRoomIds(
@Param("propertyId") propertyId: UUID,
@Param("roomIds") roomIds: List<UUID>
): List<UUID>
@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.isVoided = false
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
@Query("""
select rs
from RoomStay rs
join fetch rs.room r
join fetch r.roomType rt
join fetch rs.booking b
left join fetch b.primaryGuest g
where rs.property.id = :propertyId
and rs.toAt is null
and rs.isVoided = false
order by r.roomNumber
""")
fun findActiveByPropertyIdWithDetails(@Param("propertyId") propertyId: UUID): List<RoomStay>
@Query("""
select case when count(rs) > 0 then true else false end
from RoomStay rs
where rs.room.id = :roomId
""")
fun existsByRoomId(@Param("roomId") roomId: UUID): Boolean
@Query("""
select rs.booking.id as bookingId, r.roomNumber as roomNumber
from RoomStay rs
join rs.room r
where rs.booking.id in :bookingIds
and rs.toAt is null
and rs.isVoided = false
""")
fun findActiveRoomNumbersByBookingIds(
@Param("bookingIds") bookingIds: List<UUID>
): List<BookingRoomNumberRow>
@Query(
"""
select rs
from RoomStay rs
where rs.id = :roomStayId
and rs.booking.id = :bookingId
and rs.isVoided = false
"""
)
fun findByIdAndBookingId(
@Param("roomStayId") roomStayId: UUID,
@Param("bookingId") bookingId: UUID
): RoomStay?
@Query(
"""
select count(distinct rs.room.id)
from RoomStay rs
where rs.property.id = :propertyId
and rs.room.roomType.id = :roomTypeId
and rs.isVoided = false
and rs.fromAt < :toAt
and (rs.toAt is null or rs.toAt > :fromAt)
"""
)
fun countOccupiedByTypeInRange(
@Param("propertyId") propertyId: UUID,
@Param("roomTypeId") roomTypeId: UUID,
@Param("fromAt") fromAt: java.time.OffsetDateTime,
@Param("toAt") toAt: java.time.OffsetDateTime
): Long
}
interface BookingRoomNumberRow {
val bookingId: UUID
val roomNumber: Int
}
interface ActiveRoomStayForecastRow {
val roomId: UUID
val fromAt: java.time.OffsetDateTime
val expectedCheckoutAt: java.time.OffsetDateTime?
}