Add rate plans, room stay rates, and payments ledger
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:
@@ -2,7 +2,11 @@ package com.android.trisolarisserver.controller
|
||||
|
||||
import com.android.trisolarisserver.component.PropertyAccess
|
||||
import com.android.trisolarisserver.controller.dto.ActiveRoomStayResponse
|
||||
import com.android.trisolarisserver.controller.dto.RoomStayRateChangeRequest
|
||||
import com.android.trisolarisserver.controller.dto.RoomStayRateChangeResponse
|
||||
import com.android.trisolarisserver.models.property.Role
|
||||
import com.android.trisolarisserver.models.room.RateSource
|
||||
import com.android.trisolarisserver.models.room.RoomStay
|
||||
import com.android.trisolarisserver.repo.PropertyUserRepo
|
||||
import com.android.trisolarisserver.repo.RoomStayRepo
|
||||
import com.android.trisolarisserver.security.MyPrincipal
|
||||
@@ -10,8 +14,11 @@ 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.RequestBody
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.server.ResponseStatusException
|
||||
import java.time.OffsetDateTime
|
||||
import java.util.UUID
|
||||
|
||||
@RestController
|
||||
@@ -57,6 +64,60 @@ class RoomStays(
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/properties/{propertyId}/room-stays/{roomStayId}/change-rate")
|
||||
fun changeRate(
|
||||
@PathVariable propertyId: UUID,
|
||||
@PathVariable roomStayId: UUID,
|
||||
@AuthenticationPrincipal principal: MyPrincipal?,
|
||||
@RequestBody request: RoomStayRateChangeRequest
|
||||
): RoomStayRateChangeResponse {
|
||||
requireRole(propertyAccess, propertyId, principal, Role.ADMIN, Role.MANAGER)
|
||||
val stay = requireRoomStayForProperty(roomStayRepo, propertyId, roomStayId)
|
||||
|
||||
val effectiveAt = parseOffset(request.effectiveAt)
|
||||
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "effectiveAt required")
|
||||
if (!effectiveAt.isAfter(stay.fromAt)) {
|
||||
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "effectiveAt must be after fromAt")
|
||||
}
|
||||
if (stay.toAt != null && !effectiveAt.isBefore(stay.toAt)) {
|
||||
throw ResponseStatusException(HttpStatus.CONFLICT, "effectiveAt outside stay range")
|
||||
}
|
||||
|
||||
val newStay = splitStay(stay, effectiveAt, request)
|
||||
roomStayRepo.save(stay)
|
||||
roomStayRepo.save(newStay)
|
||||
return RoomStayRateChangeResponse(
|
||||
oldRoomStayId = stay.id!!,
|
||||
newRoomStayId = newStay.id!!,
|
||||
effectiveAt = effectiveAt.toString()
|
||||
)
|
||||
}
|
||||
|
||||
private fun splitStay(stay: RoomStay, effectiveAt: OffsetDateTime, request: RoomStayRateChangeRequest): RoomStay {
|
||||
val oldToAt = stay.toAt
|
||||
stay.toAt = effectiveAt
|
||||
return RoomStay(
|
||||
property = stay.property,
|
||||
booking = stay.booking,
|
||||
room = stay.room,
|
||||
fromAt = effectiveAt,
|
||||
toAt = oldToAt,
|
||||
rateSource = parseRateSource(request.rateSource),
|
||||
nightlyRate = request.nightlyRate,
|
||||
ratePlanCode = request.ratePlanCode,
|
||||
currency = request.currency ?: stay.property.currency,
|
||||
createdBy = stay.createdBy
|
||||
)
|
||||
}
|
||||
|
||||
private fun parseRateSource(value: String): RateSource {
|
||||
return try {
|
||||
RateSource.valueOf(value.trim())
|
||||
} catch (_: IllegalArgumentException) {
|
||||
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Unknown rate source")
|
||||
}
|
||||
}
|
||||
|
||||
private fun isAgentOnly(roles: Set<Role>): Boolean {
|
||||
if (!roles.contains(Role.AGENT)) return false
|
||||
val privileged = setOf(
|
||||
|
||||
Reference in New Issue
Block a user