diff --git a/src/main/kotlin/com/android/trisolarisserver/controller/GuestDocuments.kt b/src/main/kotlin/com/android/trisolarisserver/controller/GuestDocuments.kt index 05c99b5..1836e5c 100644 --- a/src/main/kotlin/com/android/trisolarisserver/controller/GuestDocuments.kt +++ b/src/main/kotlin/com/android/trisolarisserver/controller/GuestDocuments.kt @@ -10,8 +10,10 @@ 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.models.booking.GuestDocument +import com.android.trisolarisserver.models.booking.GuestVehicle import com.android.trisolarisserver.models.property.Role import com.android.trisolarisserver.repo.AppUserRepo +import com.android.trisolarisserver.repo.GuestVehicleRepo import com.android.trisolarisserver.repo.PropertyRepo import com.android.trisolarisserver.security.MyPrincipal import com.fasterxml.jackson.databind.ObjectMapper @@ -41,6 +43,7 @@ class GuestDocuments( private val bookingRepo: BookingRepo, private val guestDocumentRepo: GuestDocumentRepo, private val appUserRepo: AppUserRepo, + private val guestVehicleRepo: GuestVehicleRepo, private val storage: DocumentStorage, private val tokenService: DocumentTokenService, private val extractionQueue: ExtractionQueue, @@ -385,6 +388,50 @@ class GuestDocuments( document.extractedData = objectMapper.writeValueAsString(results) document.extractedAt = OffsetDateTime.now() guestDocumentRepo.save(document) + + val extractedName = cleanedValue(results[DocumentPrompts.NAME.first]) + val extractedAddress = cleanedValue(results[DocumentPrompts.ADDRESS.first]) + val guestIdValue = document.guest.id + if (guestIdValue != null && (extractedName != null || extractedAddress != null)) { + val guestEntity = guestRepo.findById(guestIdValue).orElse(null) + if (guestEntity != null) { + var updated = false + if (guestEntity.name.isNullOrBlank() && extractedName != null) { + guestEntity.name = extractedName + updated = true + } + if (guestEntity.addressText.isNullOrBlank() && extractedAddress != null) { + guestEntity.addressText = extractedAddress + updated = true + } + if (updated) { + guestEntity.updatedAt = OffsetDateTime.now() + guestRepo.save(guestEntity) + } + } + } + + val extractedVehicle = cleanedValue(results["vehicleNumber"]) + if (isYes(results["isVehiclePhoto"]) && extractedVehicle != null) { + val guestIdSafe = document.guest.id + if (guestIdSafe != null && + !guestVehicleRepo.existsByPropertyIdAndVehicleNumberIgnoreCase(propertyId, extractedVehicle) + ) { + val property = propertyRepo.findById(propertyId).orElse(null) + val guestEntity = guestRepo.findById(guestIdSafe).orElse(null) + if (property != null && guestEntity != null) { + val booking = bookingRepo.findById(document.booking.id!!).orElse(null) + guestVehicleRepo.save( + GuestVehicle( + property = property, + guest = guestEntity, + booking = booking, + vehicleNumber = extractedVehicle + ) + ) + } + } + } guestDocumentEvents.emit(propertyId, guestId) } catch (_: Exception) { // Keep upload successful even if AI extraction fails. @@ -458,3 +505,11 @@ private fun GuestDocument.toResponse(objectMapper: ObjectMapper): GuestDocumentR private fun isYes(value: String?): Boolean { return value.orEmpty().contains("YES", ignoreCase = true) } + +private fun cleanedValue(value: String?): String? { + val trimmed = value?.trim().orEmpty() + if (trimmed.isBlank()) return null + val upper = trimmed.uppercase() + if (upper == "NONE" || upper == "N/A" || upper == "NA" || upper == "NULL") return null + return trimmed +}