added auth,property db and room db,org db
This commit is contained in:
@@ -1,18 +1,201 @@
|
||||
package com.android.trisolarisserver.controller
|
||||
|
||||
import com.android.trisolarisserver.component.PropertyAccess
|
||||
import org.springframework.stereotype.Component
|
||||
import com.android.trisolarisserver.controller.dto.RoomAvailabilityResponse
|
||||
import com.android.trisolarisserver.controller.dto.RoomBoardResponse
|
||||
import com.android.trisolarisserver.controller.dto.RoomBoardStatus
|
||||
import com.android.trisolarisserver.controller.dto.RoomResponse
|
||||
import com.android.trisolarisserver.controller.dto.RoomUpsertRequest
|
||||
import com.android.trisolarisserver.db.repo.PropertyRepo
|
||||
import com.android.trisolarisserver.db.repo.PropertyUserRepo
|
||||
import com.android.trisolarisserver.db.repo.RoomRepo
|
||||
import com.android.trisolarisserver.db.repo.RoomStayRepo
|
||||
import com.android.trisolarisserver.db.repo.RoomTypeRepo
|
||||
import com.android.trisolarisserver.models.room.Room
|
||||
import com.android.trisolarisserver.models.property.Role
|
||||
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.PostMapping
|
||||
import org.springframework.web.bind.annotation.PutMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.ResponseStatus
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.server.ResponseStatusException
|
||||
import java.util.UUID
|
||||
|
||||
class Rooms {
|
||||
@RestController
|
||||
@RequestMapping("/properties/{propertyId}/rooms")
|
||||
class Rooms(
|
||||
private val propertyAccess: PropertyAccess,
|
||||
private val roomRepo: RoomRepo,
|
||||
private val roomStayRepo: RoomStayRepo,
|
||||
private val propertyRepo: PropertyRepo,
|
||||
private val roomTypeRepo: RoomTypeRepo,
|
||||
private val propertyUserRepo: PropertyUserRepo
|
||||
) {
|
||||
|
||||
// private val propertyAccess: PropertyAccess;
|
||||
// @GetMapping("/properties/{propertyId}/rooms/free")
|
||||
// fun freeRooms(@PathVariable propertyId: UUID, principal: MyPrincipal): List<RoomDto> {
|
||||
// propertyAccess.requireMember(propertyId, principal.userId)
|
||||
// return roomService.freeRooms(propertyId)
|
||||
// }
|
||||
@GetMapping
|
||||
fun listRooms(
|
||||
@PathVariable propertyId: UUID,
|
||||
@AuthenticationPrincipal principal: MyPrincipal?
|
||||
): List<RoomResponse> {
|
||||
requirePrincipal(principal)
|
||||
propertyAccess.requireMember(propertyId, principal!!.userId)
|
||||
val roles = propertyUserRepo.findRolesByPropertyAndUser(propertyId, principal.userId)
|
||||
val rooms = roomRepo.findByPropertyIdOrderByRoomNumber(propertyId)
|
||||
if (isAgentOnly(roles)) {
|
||||
val occupiedRoomIds = roomStayRepo.findOccupiedRoomIds(propertyId).toHashSet()
|
||||
return rooms
|
||||
.filter { it.active && !it.maintenance && !occupiedRoomIds.contains(it.id) }
|
||||
.map { it.toRoomResponse() }
|
||||
}
|
||||
return rooms
|
||||
.map { it.toRoomResponse() }
|
||||
}
|
||||
|
||||
}
|
||||
@GetMapping("/board")
|
||||
fun roomBoard(
|
||||
@PathVariable propertyId: UUID,
|
||||
@AuthenticationPrincipal principal: MyPrincipal?
|
||||
): List<RoomBoardResponse> {
|
||||
requirePrincipal(principal)
|
||||
propertyAccess.requireMember(propertyId, principal!!.userId)
|
||||
|
||||
val rooms = roomRepo.findByPropertyIdOrderByRoomNumber(propertyId)
|
||||
val occupiedRoomIds = roomStayRepo.findOccupiedRoomIds(propertyId).toHashSet()
|
||||
val roles = propertyUserRepo.findRolesByPropertyAndUser(propertyId, principal.userId)
|
||||
|
||||
val mapped = rooms.map { room ->
|
||||
val status = when {
|
||||
room.maintenance -> RoomBoardStatus.MAINTENANCE
|
||||
!room.active -> RoomBoardStatus.INACTIVE
|
||||
occupiedRoomIds.contains(room.id) -> RoomBoardStatus.OCCUPIED
|
||||
else -> RoomBoardStatus.FREE
|
||||
}
|
||||
RoomBoardResponse(
|
||||
roomNumber = room.roomNumber,
|
||||
roomTypeName = room.roomType.name,
|
||||
status = status
|
||||
)
|
||||
}
|
||||
return if (isAgentOnly(roles)) mapped.filter { it.status == RoomBoardStatus.FREE } else mapped
|
||||
}
|
||||
|
||||
@GetMapping("/availability")
|
||||
fun roomAvailability(
|
||||
@PathVariable propertyId: UUID,
|
||||
@AuthenticationPrincipal principal: MyPrincipal?
|
||||
): List<RoomAvailabilityResponse> {
|
||||
requirePrincipal(principal)
|
||||
propertyAccess.requireMember(propertyId, principal!!.userId)
|
||||
|
||||
val rooms = roomRepo.findByPropertyIdOrderByRoomNumber(propertyId)
|
||||
val occupiedRoomIds = roomStayRepo.findOccupiedRoomIds(propertyId).toHashSet()
|
||||
|
||||
val freeRooms = rooms.filter { it.active && !it.maintenance && !occupiedRoomIds.contains(it.id) }
|
||||
val grouped = freeRooms.groupBy { it.roomType.name }
|
||||
return grouped.entries.map { (typeName, roomList) ->
|
||||
RoomAvailabilityResponse(
|
||||
roomTypeName = typeName,
|
||||
freeRoomNumbers = roomList.map { it.roomNumber }
|
||||
)
|
||||
}.sortedBy { it.roomTypeName }
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
fun createRoom(
|
||||
@PathVariable propertyId: UUID,
|
||||
@AuthenticationPrincipal principal: MyPrincipal?,
|
||||
@RequestBody request: RoomUpsertRequest
|
||||
): RoomResponse {
|
||||
requirePrincipal(principal)
|
||||
propertyAccess.requireMember(propertyId, principal!!.userId)
|
||||
|
||||
if (roomRepo.existsByPropertyIdAndRoomNumber(propertyId, request.roomNumber)) {
|
||||
throw ResponseStatusException(HttpStatus.CONFLICT, "Room number already exists for property")
|
||||
}
|
||||
|
||||
val property = propertyRepo.findById(propertyId).orElseThrow {
|
||||
ResponseStatusException(HttpStatus.NOT_FOUND, "Property not found")
|
||||
}
|
||||
val roomType = roomTypeRepo.findByIdAndPropertyId(request.roomTypeId, propertyId)
|
||||
?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "Room type not found")
|
||||
|
||||
val room = Room(
|
||||
property = property,
|
||||
roomType = roomType,
|
||||
roomNumber = request.roomNumber,
|
||||
floor = request.floor,
|
||||
hasNfc = request.hasNfc,
|
||||
active = request.active,
|
||||
maintenance = request.maintenance,
|
||||
notes = request.notes
|
||||
)
|
||||
|
||||
return roomRepo.save(room).toRoomResponse()
|
||||
}
|
||||
|
||||
@PutMapping("/{roomId}")
|
||||
fun updateRoom(
|
||||
@PathVariable propertyId: UUID,
|
||||
@PathVariable roomId: UUID,
|
||||
@AuthenticationPrincipal principal: MyPrincipal?,
|
||||
@RequestBody request: RoomUpsertRequest
|
||||
): RoomResponse {
|
||||
requirePrincipal(principal)
|
||||
propertyAccess.requireMember(propertyId, principal!!.userId)
|
||||
|
||||
val room = roomRepo.findByIdAndPropertyId(roomId, propertyId)
|
||||
?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "Room not found for property")
|
||||
|
||||
if (roomRepo.existsByPropertyIdAndRoomNumberAndIdNot(propertyId, request.roomNumber, roomId)) {
|
||||
throw ResponseStatusException(HttpStatus.CONFLICT, "Room number already exists for property")
|
||||
}
|
||||
|
||||
val roomType = roomTypeRepo.findByIdAndPropertyId(request.roomTypeId, propertyId)
|
||||
?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "Room type not found")
|
||||
|
||||
room.roomNumber = request.roomNumber
|
||||
room.floor = request.floor
|
||||
room.roomType = roomType
|
||||
room.hasNfc = request.hasNfc
|
||||
room.active = request.active
|
||||
room.maintenance = request.maintenance
|
||||
room.notes = request.notes
|
||||
|
||||
return roomRepo.save(room).toRoomResponse()
|
||||
}
|
||||
|
||||
private fun requirePrincipal(principal: MyPrincipal?) {
|
||||
if (principal == null) {
|
||||
throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Missing principal")
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
return roles.none { it in privileged }
|
||||
}
|
||||
}
|
||||
|
||||
private fun Room.toRoomResponse(): RoomResponse {
|
||||
val roomId = id ?: throw IllegalStateException("Room id is null")
|
||||
val roomTypeId = roomType.id ?: throw IllegalStateException("Room type id is null")
|
||||
return RoomResponse(
|
||||
id = roomId,
|
||||
roomNumber = roomNumber,
|
||||
floor = floor,
|
||||
roomTypeId = roomTypeId,
|
||||
roomTypeName = roomType.name,
|
||||
hasNfc = hasNfc,
|
||||
active = active,
|
||||
maintenance = maintenance,
|
||||
notes = notes
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user