diff --git a/apps/edr-passenger-web/backoffice/src/app/bookings/page.tsx b/apps/edr-passenger-web/backoffice/src/app/bookings/page.tsx index a1909d6e8..fffe3722c 100644 --- a/apps/edr-passenger-web/backoffice/src/app/bookings/page.tsx +++ b/apps/edr-passenger-web/backoffice/src/app/bookings/page.tsx @@ -31,6 +31,9 @@ const SectionHeader = ({ title }: { title: string }) => ( function BookingsPageContent() { const canManage = usePermission(PERMS.bookings.manage); + // Mirrors the API guard on POST /payments/:bookingId/force-confirm — + // tickets:generate, with the usual super-admin / org-admin bypass. + const canGenerateTicket = usePermission(PERMS.tickets.generate); const [filters, setFilters] = useState({ page: 1, pageSize: 20, search: '', status: '' }); const [extraFilters, setExtraFilters] = useState({ bookingType: '', dateFrom: '', dateTo: '', paymentStatus: '', providerTxnId: '' }); const [showExtraFilters, setShowExtraFilters] = useState(false); @@ -298,7 +301,7 @@ function BookingsPageContent() { const actions = [ { label: 'View Details', onClick: (b: any) => setSelectedBooking(b), variant: 'secondary' as const, icon: Eye }, - { label: 'Generate Ticket', onClick: (b: any) => { setGenerateTicketForm({ paymentReference: '', paymentMethod: '', notes: '' }); setGenerateTicketTouched({ paymentReference: false, paymentMethod: false }); setGenerateTicketBooking(b); }, variant: 'secondary' as const, icon: Ticket, show: (b: any) => !(b.status === 'CONFIRMED' && b.paymentIntent?.status === 'SUCCEEDED') }, + { label: 'Generate Ticket', onClick: (b: any) => { setGenerateTicketForm({ paymentReference: '', paymentMethod: '', notes: '' }); setGenerateTicketTouched({ paymentReference: false, paymentMethod: false }); setGenerateTicketBooking(b); }, variant: 'secondary' as const, icon: Ticket, show: (b: any) => canGenerateTicket && !(b.status === 'CONFIRMED' && b.paymentIntent?.status === 'SUCCEEDED') }, { label: 'Delete', onClick: (b: any) => { setDeleteError(null); setDeleteCascade(false); setDeleteCascadeChecked(false); setBookingToDelete(b); setDeleteConfirmOpen(true); }, variant: 'danger' as const, icon: Trash2 }, ];