modes of transport
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
package com.android.trisolarisserver.controller
|
||||
|
||||
import com.android.trisolarisserver.component.PropertyAccess
|
||||
import com.android.trisolarisserver.controller.dto.GuestResponse
|
||||
import com.android.trisolarisserver.controller.dto.GuestVehicleRequest
|
||||
import com.android.trisolarisserver.models.booking.Guest
|
||||
import com.android.trisolarisserver.models.booking.GuestVehicle
|
||||
import com.android.trisolarisserver.repo.GuestRepo
|
||||
import com.android.trisolarisserver.repo.GuestVehicleRepo
|
||||
import com.android.trisolarisserver.repo.PropertyRepo
|
||||
import com.android.trisolarisserver.security.MyPrincipal
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import org.springframework.web.server.ResponseStatusException
|
||||
import java.util.UUID
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/properties/{propertyId}/guests")
|
||||
class Guests(
|
||||
private val propertyAccess: PropertyAccess,
|
||||
private val propertyRepo: PropertyRepo,
|
||||
private val guestRepo: GuestRepo,
|
||||
private val guestVehicleRepo: GuestVehicleRepo
|
||||
) {
|
||||
|
||||
@GetMapping("/search")
|
||||
fun search(
|
||||
@PathVariable propertyId: UUID,
|
||||
@AuthenticationPrincipal principal: MyPrincipal?,
|
||||
@RequestParam(required = false) phone: String?,
|
||||
@RequestParam(required = false) vehicleNumber: String?
|
||||
): List<GuestResponse> {
|
||||
requirePrincipal(principal)
|
||||
propertyAccess.requireMember(propertyId, principal!!.userId)
|
||||
|
||||
if (phone.isNullOrBlank() && vehicleNumber.isNullOrBlank()) {
|
||||
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "phone or vehicleNumber required")
|
||||
}
|
||||
|
||||
val property = propertyRepo.findById(propertyId).orElseThrow {
|
||||
ResponseStatusException(HttpStatus.NOT_FOUND, "Property not found")
|
||||
}
|
||||
val orgId = property.org.id ?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "Org missing")
|
||||
|
||||
val guests = mutableSetOf<Guest>()
|
||||
if (!phone.isNullOrBlank()) {
|
||||
val guest = guestRepo.findByOrgIdAndPhoneE164(orgId, phone)
|
||||
if (guest != null) guests.add(guest)
|
||||
}
|
||||
if (!vehicleNumber.isNullOrBlank()) {
|
||||
val vehicle = guestVehicleRepo.findByOrgIdAndVehicleNumberIgnoreCase(orgId, vehicleNumber)
|
||||
if (vehicle != null) guests.add(vehicle.guest)
|
||||
}
|
||||
return guests.toResponse(guestVehicleRepo)
|
||||
}
|
||||
|
||||
@PostMapping("/{guestId}/vehicles")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
fun addVehicle(
|
||||
@PathVariable propertyId: UUID,
|
||||
@PathVariable guestId: UUID,
|
||||
@AuthenticationPrincipal principal: MyPrincipal?,
|
||||
@RequestBody request: GuestVehicleRequest
|
||||
): GuestResponse {
|
||||
requirePrincipal(principal)
|
||||
propertyAccess.requireMember(propertyId, principal!!.userId)
|
||||
|
||||
val property = propertyRepo.findById(propertyId).orElseThrow {
|
||||
ResponseStatusException(HttpStatus.NOT_FOUND, "Property not found")
|
||||
}
|
||||
val guest = guestRepo.findById(guestId).orElseThrow {
|
||||
ResponseStatusException(HttpStatus.NOT_FOUND, "Guest not found")
|
||||
}
|
||||
if (guest.org.id != property.org.id) {
|
||||
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Guest not in property org")
|
||||
}
|
||||
if (guestVehicleRepo.existsByOrgIdAndVehicleNumberIgnoreCase(property.org.id!!, request.vehicleNumber)) {
|
||||
throw ResponseStatusException(HttpStatus.CONFLICT, "Vehicle number already exists")
|
||||
}
|
||||
|
||||
val vehicle = GuestVehicle(
|
||||
org = property.org,
|
||||
guest = guest,
|
||||
vehicleNumber = request.vehicleNumber.trim()
|
||||
)
|
||||
guestVehicleRepo.save(vehicle)
|
||||
return listOf(guest).toResponse(guestVehicleRepo).first()
|
||||
}
|
||||
|
||||
private fun requirePrincipal(principal: MyPrincipal?) {
|
||||
if (principal == null) {
|
||||
throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Missing principal")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Set<Guest>.toResponse(guestVehicleRepo: GuestVehicleRepo): List<GuestResponse> {
|
||||
val ids = this.mapNotNull { it.id }
|
||||
val vehicles = if (ids.isEmpty()) emptyList() else guestVehicleRepo.findByGuestIdIn(ids)
|
||||
val vehiclesByGuest = vehicles.groupBy { it.guest.id }
|
||||
return this.map { guest ->
|
||||
GuestResponse(
|
||||
id = guest.id!!,
|
||||
orgId = guest.org.id!!,
|
||||
name = guest.name,
|
||||
phoneE164 = guest.phoneE164,
|
||||
nationality = guest.nationality,
|
||||
addressText = guest.addressText,
|
||||
vehicleNumbers = vehiclesByGuest[guest.id]?.map { it.vehicleNumber }?.toSet() ?: emptySet()
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user