feat(bookings): allow cancelling booking confirmations

Add API endpoint to revert confirmed bookings to pending status
Add unconfirm buttons to the bookings list and confirmation page
Update inventory summary when a confirmation is cancelled
This commit is contained in:
2026-05-05 07:04:42 +08:00
parent 4e40bfd804
commit 13e85cfcd0
5 changed files with 179 additions and 3 deletions

View File

@@ -0,0 +1,31 @@
import type { CancelBookingConfirmationResponse } from '~~/shared/booking'
import { cancelBookingConfirmationByConfirmationToken, getBookingByConfirmationToken } from '../../../../utils/booking-repository'
import { getRequiredRouteParam, httpError } from '../../../../utils/http'
export default defineEventHandler(async (event): Promise<CancelBookingConfirmationResponse> => {
const token = getRequiredRouteParam(event, 'token', 'Confirmation token')
const existingBooking = await getBookingByConfirmationToken(token)
if (!existingBooking) {
httpError(404, 'Booking not found')
}
if (existingBooking.status === 'pending') {
return {
booking: existingBooking,
alreadyPending: true
}
}
const booking = await cancelBookingConfirmationByConfirmationToken(token)
if (!booking) {
httpError(404, 'Booking not found')
}
return {
booking,
alreadyPending: false
}
})

View File

@@ -859,3 +859,30 @@ export async function confirmBookingByConfirmationToken(confirmationToken: strin
return await getBookingByConfirmationToken(confirmationToken)
}
export async function cancelBookingConfirmationByConfirmationToken(confirmationToken: string): Promise<PublicBooking | null> {
await ensureDatabaseReady()
const sql = getSqlClient()
const [row] = await sql<DbBookingRow[]>`
with updated_booking as (
update bookings
set
status = 'pending',
confirmed_at = null,
updated_at = now()
where confirmation_token = ${confirmationToken}
and status = 'confirmed'
returning *
)
select ${bookingSelectColumns(sql)}
from updated_booking as bookings
${bookingJoins(sql)}
`
if (row) {
return mapBooking(row)
}
return await getBookingByConfirmationToken(confirmationToken)
}