reservation implementation

This commit is contained in:
root
2026-06-11 15:35:25 -04:00
parent 6eeba99c45
commit 37a6ed8a76
30 changed files with 2598 additions and 477 deletions
@@ -5,7 +5,7 @@ import { validateLicense } from '../../services/licenseValidationService'
import { sendNotification, sendTransactionalEmail } from '../../services/notificationService'
import { reviewRequestEmail, type Lang } from '../../lib/emailTranslations'
import { coerceNotificationLocale } from '../../services/notificationLocalizationService'
import { buildReservationWorkflow, parseReservationExtras, serializeReservationForDashboard } from './reservation.presenter'
import { buildBookingRequestProgress, buildReservationWorkflow, parseReservationExtras, serializeReservationForDashboard } from './reservation.presenter'
import * as repo from './reservation.repo'
function buildPickupAddress(value: unknown) {
@@ -47,7 +47,6 @@ async function assertLicenseCompliance(reservationId: string, companyId: string)
export async function confirmReservation(id: string, companyId: string) {
const reservation = await repo.findByIdSimple(id, companyId)
if (reservation.status !== 'DRAFT') throw new AppError('Only DRAFT reservations can be confirmed', 400, 'invalid_status')
await assertLicenseCompliance(reservation.id, companyId)
const updated = await repo.updateById(id, { status: 'CONFIRMED' })
await repo.updateVehicleStatus(reservation.vehicleId, 'RESERVED')
@@ -97,6 +96,44 @@ export async function confirmReservation(id: string, companyId: string) {
},
}).catch(() => null)
if (reservation.source === 'MARKETPLACE') {
const progress = buildBookingRequestProgress({
source: reservation.source,
status: 'CONFIRMED',
paymentStatus: updated.paymentStatus,
customer,
})
const reminderChannels = reservation.renterId ? ['EMAIL', 'IN_APP'] as const : ['EMAIL'] as const
if (progress.documentsRequired) {
await sendNotification({
type: 'DOCUMENTS_REQUIRED',
companyId,
renterId: reservation.renterId ?? undefined,
email: customer.email,
channels: [...reminderChannels],
locale: reservation.renterId ? undefined : fallbackLocale,
title: 'Driver documents still needed',
body: `${company?.brand?.displayName ?? company?.name ?? 'The rental company'} confirmed availability. Please send the remaining driver documents so the booking can move forward.`,
data: { reservationId: reservation.id, missingItems: progress.documentsMissing },
}).catch(() => null)
}
if (progress.paymentRequired) {
await sendNotification({
type: 'PAYMENT_REQUIRED',
companyId,
renterId: reservation.renterId ?? undefined,
email: customer.email,
channels: [...reminderChannels],
locale: reservation.renterId ? undefined : fallbackLocale,
title: 'Payment or deposit is still pending',
body: `${company?.brand?.displayName ?? company?.name ?? 'The rental company'} accepted your request. Complete any required payment or deposit to finalize the booking.`,
data: { reservationId: reservation.id, paymentStatus: updated.paymentStatus },
}).catch(() => null)
}
}
return updated
}