125 lines
4.6 KiB
Kotlin
125 lines
4.6 KiB
Kotlin
package com.android.trisolarisserver.controller
|
|
|
|
import com.android.trisolarisserver.controller.dto.AmenityResponse
|
|
import com.android.trisolarisserver.controller.dto.AmenityUpsertRequest
|
|
import com.android.trisolarisserver.models.room.RoomAmenity
|
|
import com.android.trisolarisserver.repo.AppUserRepo
|
|
import com.android.trisolarisserver.repo.RoomAmenityRepo
|
|
import com.android.trisolarisserver.repo.RoomTypeRepo
|
|
import com.android.trisolarisserver.security.MyPrincipal
|
|
import org.springframework.http.HttpStatus
|
|
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
|
import org.springframework.web.bind.annotation.DeleteMapping
|
|
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
|
|
|
|
@RestController
|
|
@RequestMapping("/amenities")
|
|
class RoomAmenities(
|
|
private val roomAmenityRepo: RoomAmenityRepo,
|
|
private val roomTypeRepo: RoomTypeRepo,
|
|
private val appUserRepo: AppUserRepo
|
|
) {
|
|
|
|
@GetMapping
|
|
fun listAmenities(
|
|
@AuthenticationPrincipal principal: MyPrincipal?
|
|
): List<AmenityResponse> {
|
|
requirePrincipal(principal)
|
|
return roomAmenityRepo.findAllByOrderByName().map { it.toResponse() }
|
|
}
|
|
|
|
@PostMapping
|
|
@ResponseStatus(HttpStatus.CREATED)
|
|
fun createAmenity(
|
|
@AuthenticationPrincipal principal: MyPrincipal?,
|
|
@RequestBody request: AmenityUpsertRequest
|
|
): AmenityResponse {
|
|
requireSuperAdmin(principal)
|
|
|
|
if (roomAmenityRepo.existsByName(request.name)) {
|
|
throw ResponseStatusException(HttpStatus.CONFLICT, "Amenity already exists")
|
|
}
|
|
val amenity = RoomAmenity(
|
|
name = request.name,
|
|
category = request.category,
|
|
iconKey = request.iconKey
|
|
)
|
|
return roomAmenityRepo.save(amenity).toResponse()
|
|
}
|
|
|
|
@PutMapping("/{amenityId}")
|
|
fun updateAmenity(
|
|
@PathVariable amenityId: UUID,
|
|
@AuthenticationPrincipal principal: MyPrincipal?,
|
|
@RequestBody request: AmenityUpsertRequest
|
|
): AmenityResponse {
|
|
requireSuperAdmin(principal)
|
|
|
|
val amenity = roomAmenityRepo.findById(amenityId).orElse(null)
|
|
?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "Amenity not found")
|
|
|
|
if (roomAmenityRepo.existsByNameAndIdNot(request.name, amenityId)) {
|
|
throw ResponseStatusException(HttpStatus.CONFLICT, "Amenity already exists")
|
|
}
|
|
|
|
amenity.name = request.name
|
|
amenity.category = request.category ?: amenity.category
|
|
amenity.iconKey = request.iconKey ?: amenity.iconKey
|
|
return roomAmenityRepo.save(amenity).toResponse()
|
|
}
|
|
|
|
@DeleteMapping("/{amenityId}")
|
|
@ResponseStatus(HttpStatus.NO_CONTENT)
|
|
fun deleteAmenity(
|
|
@PathVariable amenityId: UUID,
|
|
@AuthenticationPrincipal principal: MyPrincipal?
|
|
) {
|
|
requireSuperAdmin(principal)
|
|
|
|
val amenity = roomAmenityRepo.findById(amenityId).orElse(null)
|
|
?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "Amenity not found")
|
|
|
|
if (roomTypeRepo.existsByAmenitiesId(amenityId)) {
|
|
throw ResponseStatusException(HttpStatus.CONFLICT, "Amenity is used by room types")
|
|
}
|
|
roomAmenityRepo.delete(amenity)
|
|
}
|
|
|
|
private fun requirePrincipal(principal: MyPrincipal?) {
|
|
if (principal == null) {
|
|
throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Missing principal")
|
|
}
|
|
}
|
|
|
|
private fun requireSuperAdmin(principal: MyPrincipal?) {
|
|
if (principal == null) {
|
|
throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Missing principal")
|
|
}
|
|
val user = appUserRepo.findById(principal.userId).orElseThrow {
|
|
ResponseStatusException(HttpStatus.UNAUTHORIZED, "User not found")
|
|
}
|
|
if (!user.superAdmin) {
|
|
throw ResponseStatusException(HttpStatus.FORBIDDEN, "Super admin only")
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun RoomAmenity.toResponse(): AmenityResponse {
|
|
val id = id ?: throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Amenity id missing")
|
|
return AmenityResponse(
|
|
id = id,
|
|
name = name,
|
|
category = category,
|
|
iconKey = iconKey
|
|
)
|
|
}
|