Add booking create endpoint
All checks were successful
build-and-deploy / build-deploy (push) Successful in 34s
All checks were successful
build-and-deploy / build-deploy (push) Successful in 34s
This commit is contained in:
@@ -95,6 +95,7 @@ Properties
|
|||||||
- Property create/update accepts addressText, otaAliases, emailAddresses, allowedTransportModes.
|
- Property create/update accepts addressText, otaAliases, emailAddresses, allowedTransportModes.
|
||||||
|
|
||||||
Booking flow
|
Booking flow
|
||||||
|
- POST /properties/{propertyId}/bookings (create booking)
|
||||||
- /properties/{propertyId}/bookings/{bookingId}/check-in (creates RoomStay rows)
|
- /properties/{propertyId}/bookings/{bookingId}/check-in (creates RoomStay rows)
|
||||||
- /properties/{propertyId}/bookings/{bookingId}/check-out (closes RoomStay)
|
- /properties/{propertyId}/bookings/{bookingId}/check-out (closes RoomStay)
|
||||||
- /properties/{propertyId}/bookings/{bookingId}/cancel
|
- /properties/{propertyId}/bookings/{bookingId}/cancel
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import com.android.trisolarisserver.component.RoomBoardEvents
|
|||||||
import com.android.trisolarisserver.controller.dto.BookingCancelRequest
|
import com.android.trisolarisserver.controller.dto.BookingCancelRequest
|
||||||
import com.android.trisolarisserver.controller.dto.BookingCheckInRequest
|
import com.android.trisolarisserver.controller.dto.BookingCheckInRequest
|
||||||
import com.android.trisolarisserver.controller.dto.BookingCheckOutRequest
|
import com.android.trisolarisserver.controller.dto.BookingCheckOutRequest
|
||||||
|
import com.android.trisolarisserver.controller.dto.BookingCreateRequest
|
||||||
|
import com.android.trisolarisserver.controller.dto.BookingCreateResponse
|
||||||
import com.android.trisolarisserver.controller.dto.BookingNoShowRequest
|
import com.android.trisolarisserver.controller.dto.BookingNoShowRequest
|
||||||
import com.android.trisolarisserver.controller.dto.RoomStayPreAssignRequest
|
import com.android.trisolarisserver.controller.dto.RoomStayPreAssignRequest
|
||||||
import com.android.trisolarisserver.db.repo.BookingRepo
|
import com.android.trisolarisserver.db.repo.BookingRepo
|
||||||
@@ -13,6 +15,7 @@ import com.android.trisolarisserver.models.booking.TransportMode
|
|||||||
import com.android.trisolarisserver.models.room.RoomStay
|
import com.android.trisolarisserver.models.room.RoomStay
|
||||||
import com.android.trisolarisserver.models.property.Role
|
import com.android.trisolarisserver.models.property.Role
|
||||||
import com.android.trisolarisserver.repo.AppUserRepo
|
import com.android.trisolarisserver.repo.AppUserRepo
|
||||||
|
import com.android.trisolarisserver.repo.PropertyRepo
|
||||||
import com.android.trisolarisserver.repo.RoomRepo
|
import com.android.trisolarisserver.repo.RoomRepo
|
||||||
import com.android.trisolarisserver.repo.RoomStayRepo
|
import com.android.trisolarisserver.repo.RoomStayRepo
|
||||||
import com.android.trisolarisserver.security.MyPrincipal
|
import com.android.trisolarisserver.security.MyPrincipal
|
||||||
@@ -37,9 +40,62 @@ class BookingFlow(
|
|||||||
private val roomRepo: RoomRepo,
|
private val roomRepo: RoomRepo,
|
||||||
private val roomStayRepo: RoomStayRepo,
|
private val roomStayRepo: RoomStayRepo,
|
||||||
private val appUserRepo: AppUserRepo,
|
private val appUserRepo: AppUserRepo,
|
||||||
|
private val propertyRepo: PropertyRepo,
|
||||||
private val roomBoardEvents: RoomBoardEvents
|
private val roomBoardEvents: RoomBoardEvents
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
@ResponseStatus(HttpStatus.CREATED)
|
||||||
|
@Transactional
|
||||||
|
fun createBooking(
|
||||||
|
@PathVariable propertyId: UUID,
|
||||||
|
@AuthenticationPrincipal principal: MyPrincipal?,
|
||||||
|
@RequestBody request: BookingCreateRequest
|
||||||
|
): BookingCreateResponse {
|
||||||
|
val actor = requireActor(propertyId, principal)
|
||||||
|
val property = propertyRepo.findById(propertyId).orElseThrow {
|
||||||
|
ResponseStatusException(HttpStatus.NOT_FOUND, "Property not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
val expectedCheckInAt = parseOffset(request.expectedCheckInAt)
|
||||||
|
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "expectedCheckInAt required")
|
||||||
|
val expectedCheckOutAt = parseOffset(request.expectedCheckOutAt)
|
||||||
|
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "expectedCheckOutAt required")
|
||||||
|
if (!expectedCheckOutAt.isAfter(expectedCheckInAt)) {
|
||||||
|
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid date range")
|
||||||
|
}
|
||||||
|
|
||||||
|
val now = OffsetDateTime.now()
|
||||||
|
val booking = com.android.trisolarisserver.models.booking.Booking(
|
||||||
|
property = property,
|
||||||
|
status = BookingStatus.OPEN,
|
||||||
|
source = request.source?.trim().takeIf { !it.isNullOrBlank() } ?: "WALKIN",
|
||||||
|
expectedCheckinAt = expectedCheckInAt,
|
||||||
|
expectedCheckoutAt = expectedCheckOutAt,
|
||||||
|
transportMode = request.transportMode?.let {
|
||||||
|
val mode = parseTransportMode(it)
|
||||||
|
if (!isTransportModeAllowed(property, mode)) {
|
||||||
|
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Transport mode disabled")
|
||||||
|
}
|
||||||
|
mode
|
||||||
|
},
|
||||||
|
transportVehicleNumber = request.transportVehicleNumber,
|
||||||
|
adultCount = request.adultCount,
|
||||||
|
totalGuestCount = request.totalGuestCount,
|
||||||
|
notes = request.notes,
|
||||||
|
createdBy = actor,
|
||||||
|
updatedAt = now
|
||||||
|
)
|
||||||
|
|
||||||
|
val saved = bookingRepo.save(booking)
|
||||||
|
return BookingCreateResponse(
|
||||||
|
id = saved.id!!,
|
||||||
|
status = saved.status.name,
|
||||||
|
expectedCheckInAt = expectedCheckInAt.toString(),
|
||||||
|
expectedCheckOutAt = expectedCheckOutAt.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/{bookingId}/check-in")
|
@PostMapping("/{bookingId}/check-in")
|
||||||
@ResponseStatus(HttpStatus.CREATED)
|
@ResponseStatus(HttpStatus.CREATED)
|
||||||
@Transactional
|
@Transactional
|
||||||
|
|||||||
@@ -10,6 +10,24 @@ data class BookingCheckInRequest(
|
|||||||
val notes: String? = null
|
val notes: String? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class BookingCreateRequest(
|
||||||
|
val source: String? = null,
|
||||||
|
val expectedCheckInAt: String,
|
||||||
|
val expectedCheckOutAt: String,
|
||||||
|
val transportMode: String? = null,
|
||||||
|
val transportVehicleNumber: String? = null,
|
||||||
|
val adultCount: Int? = null,
|
||||||
|
val totalGuestCount: Int? = null,
|
||||||
|
val notes: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
data class BookingCreateResponse(
|
||||||
|
val id: UUID,
|
||||||
|
val status: String,
|
||||||
|
val expectedCheckInAt: String,
|
||||||
|
val expectedCheckOutAt: String
|
||||||
|
)
|
||||||
|
|
||||||
data class BookingCheckOutRequest(
|
data class BookingCheckOutRequest(
|
||||||
val checkOutAt: String? = null,
|
val checkOutAt: String? = null,
|
||||||
val notes: String? = null
|
val notes: String? = null
|
||||||
|
|||||||
Reference in New Issue
Block a user