diff --git a/apps/edr-passenger-api/src/modules/payments/payments.service.ts b/apps/edr-passenger-api/src/modules/payments/payments.service.ts index e9e4d2636..7ee67be76 100644 --- a/apps/edr-passenger-api/src/modules/payments/payments.service.ts +++ b/apps/edr-passenger-api/src/modules/payments/payments.service.ts @@ -900,6 +900,9 @@ export class PaymentsService { this.logger.error( `Error generating ticket for booking ${booking.id}: ${err instanceof Error ? err.message : String(err)}`, ); + // Re-throw so callers (e.g. force-confirm) know tickets weren't issued. + // Webhook handlers catch this themselves and still return 200 to avoid redelivery. + throw err; } try { @@ -1012,6 +1015,11 @@ export class PaymentsService { intentId: intent.id, providerTxnId: event.providerTxnId, paidAt: event.paidAt ? new Date(event.paidAt) : undefined, + }).catch((err) => { + this.logger.error( + `finalizePaymentSuccess failed for booking ${event.referenceId}: ${err instanceof Error ? err.message : String(err)}`, + ); + return { alreadyFinalized: false }; }); return { processed: true, alreadyFinalized }; } diff --git a/apps/edr-passenger-web/portal/src/app/booking/detail/page.tsx b/apps/edr-passenger-web/portal/src/app/booking/detail/page.tsx index c6e6a4817..c6f823053 100644 --- a/apps/edr-passenger-web/portal/src/app/booking/detail/page.tsx +++ b/apps/edr-passenger-web/portal/src/app/booking/detail/page.tsx @@ -249,8 +249,20 @@ function BookingDetailContent() { setIsGeneratingVoucher(true); try { + // If tickets are missing (generate failed silently at payment time), issue them now. + if (!booking.tickets?.length && booking.id) { + try { + await apiClient.post(`/tickets/generate/${booking.id}`, {}); + } catch { + // ignore — generate() will throw if payment not succeeded; voucher will show + // "Not yet issued" in that case, which is correct + } + } + // Always refetch so the voucher has the latest ticket barcodes. + const fresh = await apiClient.get(`/bookings/${booking.bookingRef}`); + const bookingData = (fresh as any)?.data || fresh; const { generateVoucherPDF } = await import("@/lib/generate-voucher"); - await generateVoucherPDF(booking as any); + await generateVoucherPDF(bookingData as any); } catch (error) { alert( `Failed to generate voucher: ${error instanceof Error ? error.message : "Unknown error"}`,