diff --git a/src/main/kotlin/com/android/trisolarisserver/controller/Rooms.kt b/src/main/kotlin/com/android/trisolarisserver/controller/Rooms.kt index 0ff0584..c3ae6ef 100644 --- a/src/main/kotlin/com/android/trisolarisserver/controller/Rooms.kt +++ b/src/main/kotlin/com/android/trisolarisserver/controller/Rooms.kt @@ -10,6 +10,7 @@ import com.android.trisolarisserver.controller.dto.RoomResponse import com.android.trisolarisserver.controller.dto.RoomUpsertRequest import com.android.trisolarisserver.repo.PropertyRepo import com.android.trisolarisserver.repo.PropertyUserRepo +import com.android.trisolarisserver.repo.RoomImageRepo import com.android.trisolarisserver.repo.RoomRepo import com.android.trisolarisserver.repo.RoomStayRepo import com.android.trisolarisserver.repo.RoomTypeRepo @@ -22,6 +23,7 @@ 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.DeleteMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.ResponseStatus @@ -30,6 +32,8 @@ import org.springframework.web.server.ResponseStatusException import org.springframework.web.servlet.mvc.method.annotation.SseEmitter import java.time.LocalDate import java.time.ZoneId +import java.nio.file.Files +import java.nio.file.Paths import java.util.UUID @RestController @@ -37,6 +41,7 @@ import java.util.UUID class Rooms( private val propertyAccess: PropertyAccess, private val roomRepo: RoomRepo, + private val roomImageRepo: RoomImageRepo, private val roomStayRepo: RoomStayRepo, private val propertyRepo: PropertyRepo, private val roomTypeRepo: RoomTypeRepo, @@ -246,6 +251,40 @@ class Rooms( return response } + @DeleteMapping("/{roomId}") + @ResponseStatus(HttpStatus.NO_CONTENT) + fun deleteRoom( + @PathVariable propertyId: UUID, + @PathVariable roomId: UUID, + @AuthenticationPrincipal principal: MyPrincipal? + ) { + requirePrincipal(principal) + propertyAccess.requireMember(propertyId, principal!!.userId) + propertyAccess.requireAnyRole(propertyId, principal.userId, Role.ADMIN, Role.MANAGER) + + val room = roomRepo.findByIdAndPropertyId(roomId, propertyId) + ?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "Room not found for property") + + if (roomStayRepo.existsByRoomId(roomId)) { + throw ResponseStatusException(HttpStatus.CONFLICT, "Cannot delete room with stays") + } + + val images = roomImageRepo.findByRoomIdOrdered(roomId) + for (img in images) { + try { + Files.deleteIfExists(Paths.get(img.originalPath)) + Files.deleteIfExists(Paths.get(img.thumbnailPath)) + } catch (ex: Exception) { + throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to delete room image files") + } + } + if (images.isNotEmpty()) { + roomImageRepo.deleteAll(images) + } + roomRepo.delete(room) + roomBoardEvents.emit(propertyId) + } + private fun requirePrincipal(principal: MyPrincipal?) { if (principal == null) { throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Missing principal") diff --git a/src/main/kotlin/com/android/trisolarisserver/repo/RoomStayRepo.kt b/src/main/kotlin/com/android/trisolarisserver/repo/RoomStayRepo.kt index a512b6f..dbc403a 100644 --- a/src/main/kotlin/com/android/trisolarisserver/repo/RoomStayRepo.kt +++ b/src/main/kotlin/com/android/trisolarisserver/repo/RoomStayRepo.kt @@ -75,4 +75,11 @@ interface RoomStayRepo : JpaRepository { order by r.roomNumber """) fun findActiveByPropertyIdWithDetails(@Param("propertyId") propertyId: UUID): List + + @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 }