Add active room stays endpoint
All checks were successful
build-and-deploy / build-deploy (push) Successful in 27s

This commit is contained in:
androidlover5842
2026-01-27 00:37:27 +05:30
parent 22a9fdc851
commit 0efce2f900
3 changed files with 105 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
package com.android.trisolarisserver.controller
import com.android.trisolarisserver.component.PropertyAccess
import com.android.trisolarisserver.controller.dto.ActiveRoomStayResponse
import com.android.trisolarisserver.models.property.Role
import com.android.trisolarisserver.repo.PropertyUserRepo
import com.android.trisolarisserver.repo.RoomStayRepo
import com.android.trisolarisserver.security.MyPrincipal
import org.springframework.http.HttpStatus
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.server.ResponseStatusException
import java.util.UUID
@RestController
class RoomStays(
private val propertyAccess: PropertyAccess,
private val propertyUserRepo: PropertyUserRepo,
private val roomStayRepo: RoomStayRepo
) {
@GetMapping("/properties/{propertyId}/room-stays/active")
fun listActiveRoomStays(
@PathVariable propertyId: UUID,
@AuthenticationPrincipal principal: MyPrincipal?
): List<ActiveRoomStayResponse> {
if (principal == null) {
throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Missing principal")
}
propertyAccess.requireMember(propertyId, principal.userId)
val roles = propertyUserRepo.findRolesByPropertyAndUser(propertyId, principal.userId)
if (isAgentOnly(roles)) {
throw ResponseStatusException(HttpStatus.FORBIDDEN, "Agents cannot view active stays")
}
return roomStayRepo.findActiveByPropertyIdWithDetails(propertyId).map { stay ->
val booking = stay.booking
val guest = booking.primaryGuest
val room = stay.room
val roomType = room.roomType
ActiveRoomStayResponse(
roomStayId = stay.id!!,
bookingId = booking.id!!,
guestId = guest?.id,
guestName = guest?.name,
guestPhone = guest?.phoneE164,
roomId = room.id!!,
roomNumber = room.roomNumber,
roomTypeId = roomType.id!!,
roomTypeName = roomType.name,
fromAt = stay.fromAt.toString(),
checkinAt = booking.checkinAt?.toString(),
expectedCheckoutAt = booking.expectedCheckoutAt?.toString()
)
}
}
private fun isAgentOnly(roles: Set<Role>): Boolean {
if (!roles.contains(Role.AGENT)) return false
val privileged = setOf(
Role.ADMIN,
Role.MANAGER,
Role.STAFF,
Role.HOUSEKEEPING,
Role.FINANCE,
Role.SUPERVISOR,
Role.GUIDE
)
return roles.none { it in privileged }
}
}

View File

@@ -0,0 +1,18 @@
package com.android.trisolarisserver.controller.dto
import java.util.UUID
data class ActiveRoomStayResponse(
val roomStayId: UUID,
val bookingId: UUID,
val guestId: UUID?,
val guestName: String?,
val guestPhone: String?,
val roomId: UUID,
val roomNumber: Int,
val roomTypeId: UUID,
val roomTypeName: String,
val fromAt: String,
val checkinAt: String?,
val expectedCheckoutAt: String?
)

View File

@@ -62,4 +62,17 @@ interface RoomStayRepo : JpaRepository<RoomStay, UUID> {
@Param("fromAt") fromAt: java.time.OffsetDateTime, @Param("fromAt") fromAt: java.time.OffsetDateTime,
@Param("toAt") toAt: java.time.OffsetDateTime @Param("toAt") toAt: java.time.OffsetDateTime
): Boolean ): 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
order by r.roomNumber
""")
fun findActiveByPropertyIdWithDetails(@Param("propertyId") propertyId: UUID): List<RoomStay>
} }