Replace placeholder guest with existing phone guest
All checks were successful
build-and-deploy / build-deploy (push) Successful in 35s

This commit is contained in:
androidlover5842
2026-01-29 07:18:38 +05:30
parent 1033035f7d
commit 355da34659
5 changed files with 48 additions and 2 deletions

View File

@@ -8,6 +8,7 @@ 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.db.repo.BookingRepo
import com.android.trisolarisserver.db.repo.GuestDocumentRepo
import com.android.trisolarisserver.db.repo.GuestRepo
import com.android.trisolarisserver.db.repo.GuestRatingRepo
import com.android.trisolarisserver.repo.AppUserRepo
@@ -19,6 +20,7 @@ import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.transaction.annotation.Transactional
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile
import org.springframework.web.server.ResponseStatusException
@@ -34,12 +36,14 @@ class Guests(
private val bookingRepo: BookingRepo,
private val guestVehicleRepo: GuestVehicleRepo,
private val guestRatingRepo: GuestRatingRepo,
private val guestDocumentRepo: GuestDocumentRepo,
private val signatureStorage: GuestSignatureStorage,
private val appUserRepo: AppUserRepo
) {
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
@Transactional
fun createGuest(
@PathVariable propertyId: UUID,
@AuthenticationPrincipal principal: MyPrincipal?,
@@ -55,15 +59,26 @@ class Guests(
if (booking.property.id != property.id) {
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Booking not in property")
}
if (booking.primaryGuest != null) {
throw ResponseStatusException(HttpStatus.CONFLICT, "Booking already linked to guest")
val currentGuest = booking.primaryGuest
if (currentGuest != null && phone == null) {
if (!isPlaceholderGuest(currentGuest)) {
throw ResponseStatusException(HttpStatus.CONFLICT, "Booking already linked to guest")
}
val updated = applyGuestDetails(currentGuest, request)
booking.updatedAt = OffsetDateTime.now()
bookingRepo.save(booking)
return setOf(updated).toResponse(propertyId, guestVehicleRepo, guestRatingRepo).first()
}
if (phone != null) {
val existing = guestRepo.findByPropertyIdAndPhoneE164(propertyId, phone)
if (existing != null) {
val previous = booking.primaryGuest
booking.primaryGuest = existing
booking.updatedAt = OffsetDateTime.now()
bookingRepo.save(booking)
if (previous != null && previous.id != existing.id && isPlaceholderGuest(previous) && isSafeToDelete(previous)) {
guestRepo.delete(previous)
}
return setOf(existing).toResponse(propertyId, guestVehicleRepo, guestRatingRepo).first()
}
}
@@ -196,6 +211,33 @@ class Guests(
.body(resource)
}
private fun applyGuestDetails(guest: Guest, request: GuestCreateRequest): Guest {
val name = request.name?.trim()?.ifBlank { null }
val nationality = request.nationality?.trim()?.ifBlank { null }
val address = request.addressText?.trim()?.ifBlank { null }
if (name != null) guest.name = name
if (nationality != null) guest.nationality = nationality
if (address != null) guest.addressText = address
guest.updatedAt = OffsetDateTime.now()
return guestRepo.save(guest)
}
private fun isPlaceholderGuest(guest: Guest): Boolean {
return guest.phoneE164.isNullOrBlank() &&
guest.name.isNullOrBlank() &&
guest.nationality.isNullOrBlank() &&
guest.addressText.isNullOrBlank() &&
guest.signaturePath.isNullOrBlank()
}
private fun isSafeToDelete(guest: Guest): Boolean {
val id = guest.id ?: return false
if (bookingRepo.countByPrimaryGuestId(id) > 0) return false
if (guestVehicleRepo.existsByGuestId(id)) return false
if (guestDocumentRepo.existsByGuestId(id)) return false
if (guestRatingRepo.existsByGuestId(id)) return false
return true
}
}
private fun Set<Guest>.toResponse(

View File

@@ -7,4 +7,5 @@ import java.util.UUID
interface BookingRepo : JpaRepository<Booking, UUID> {
fun findByPropertyIdAndSourceBookingId(propertyId: UUID, sourceBookingId: String): Booking?
fun existsByPropertyIdAndSourceBookingId(propertyId: UUID, sourceBookingId: String): Boolean
fun countByPrimaryGuestId(guestId: UUID): Long
}

View File

@@ -7,4 +7,5 @@ import java.util.UUID
interface GuestDocumentRepo : JpaRepository<GuestDocument, UUID> {
fun findByPropertyIdAndGuestIdOrderByUploadedAtDesc(propertyId: UUID, guestId: UUID): List<GuestDocument>
fun findByIdAndPropertyIdAndGuestId(id: UUID, propertyId: UUID, guestId: UUID): GuestDocument?
fun existsByGuestId(guestId: UUID): Boolean
}

View File

@@ -9,6 +9,7 @@ import java.util.UUID
interface GuestRatingRepo : JpaRepository<GuestRating, UUID> {
fun findByGuestIdOrderByCreatedAtDesc(guestId: UUID): List<GuestRating>
fun existsByGuestIdAndBookingId(guestId: UUID, bookingId: UUID): Boolean
fun existsByGuestId(guestId: UUID): Boolean
@Query(
"""

View File

@@ -8,4 +8,5 @@ interface GuestVehicleRepo : JpaRepository<GuestVehicle, UUID> {
fun findByPropertyIdAndVehicleNumberIgnoreCase(propertyId: UUID, vehicleNumber: String): GuestVehicle?
fun findByGuestIdIn(guestIds: List<UUID>): List<GuestVehicle>
fun existsByPropertyIdAndVehicleNumberIgnoreCase(propertyId: UUID, vehicleNumber: String): Boolean
fun existsByGuestId(guestId: UUID): Boolean
}