feat(booking): move event and ticket configuration to database

Replace hardcoded event details and ticket types with dynamic DB records
Add booking-config API endpoint to serve active event settings
This commit is contained in:
2026-05-04 10:09:08 +08:00
parent 06165f80db
commit 3f7025c8e4
13 changed files with 970 additions and 342 deletions

View File

@@ -1,9 +1,13 @@
import type { BookingMode, CreateBookingResponse, TicketType } from '~~/shared/booking'
import { getTicketCatalogItem, getSeatCount } from '~~/shared/booking'
import { getSeatCount } from '~~/shared/booking'
import { buildAppUrl } from '../../utils/app-url'
import { createBooking } from '../../utils/booking-repository'
import {
createBooking,
getActiveBookingModeOptionByCode,
getActiveTicketCatalogItemByCode
} from '../../utils/booking-repository'
import { buildBookingMessage, parseCreateBookingInput } from '../../utils/bookings'
import { assertBadRequest } from '../../utils/http'
import { getPublicContactById } from '../../utils/user-repository'
@@ -20,29 +24,33 @@ export default defineEventHandler(async (event): Promise<CreateBookingResponse>
}>(event)
const input = parseCreateBookingInput(body)
const personInCharge = await getPublicContactById(input.personInChargeId)
const [personInCharge, bookingMode, ticket] = await Promise.all([
getPublicContactById(input.personInChargeId),
getActiveBookingModeOptionByCode(input.bookingMode),
getActiveTicketCatalogItemByCode(input.ticketType)
])
assertBadRequest(personInCharge, 'Selected person in charge is not available')
const ticket = getTicketCatalogItem(input.ticketType)
assertBadRequest(bookingMode, 'Booking mode is invalid')
assertBadRequest(ticket, 'Ticket category is invalid')
assertBadRequest(bookingMode.eventId === ticket.eventId, 'Booking mode and ticket category must belong to the same event')
const seatCount = getSeatCount(input.bookingMode, input.quantity)
const seatCount = getSeatCount(bookingMode, input.quantity)
const totalPrice = seatCount * ticket.price
const { booking, confirmationToken } = await createBooking({
eventId: bookingMode.eventId,
customerName: input.customerName,
customerPhone: input.customerPhone,
bookingMode: input.bookingMode,
bookingModeId: bookingMode.id,
bookingMode: bookingMode.value,
quantity: input.quantity,
seatCount,
ticketType: input.ticketType,
ticketTypeId: ticket.id,
ticketType: ticket.value,
unitPrice: ticket.price,
totalPrice,
personInChargeId: personInCharge.id,
personInChargeName: personInCharge.fullName,
personInChargePhoneNumber: personInCharge.phoneNumber
personInChargeId: personInCharge.id
})
const confirmationUrl = buildAppUrl(event, `/confirmation/${confirmationToken}`)