Include coach number to voucher

This commit is contained in:
Roba Boru
2026-07-19 23:58:14 +03:00
parent a6e4f0538c
commit c31a337a98
2 changed files with 43 additions and 28 deletions

View File

@@ -263,21 +263,24 @@ export default function ConfirmationPage() {
const ticketNumber = matchedTicket?.barcodePayload || "Not yet issued";
await generatePassengerVoucherPDF({
bookingRef: pnr,
bookingRef: pnr,
ticketNumber,
passengerName: p.name || `Passenger ${i + 1}`,
dateOfBirth: p.dateOfBirth,
nationality: p.nationality,
seatNumber: p.seatNumber,
outboundSeatNumber: (p as any).outboundSeatNumber,
inboundSeatNumber: (p as any).inboundSeatNumber,
passengerName: p.name || `Passenger ${i + 1}`,
dateOfBirth: p.dateOfBirth,
nationality: p.nationality,
seatNumber: p.seatNumber,
coachNumber: p.coachNumber,
outboundSeatNumber: p.outboundSeatNumber,
outboundCoachNumber: p.outboundCoachNumber,
inboundSeatNumber: p.inboundSeatNumber,
inboundCoachNumber: p.inboundCoachNumber,
status,
outboundSchedule: outbound,
inboundSchedule: inbound,
outboundSchedule: outbound,
inboundSchedule: inbound,
isRoundTrip,
fareMinor: hasSettledAmount ? settledAmountMinor! : getEtbFare(i),
currency: voucherCurrency,
fareIsMajorUnits: hasSettledAmount,
fareMinor: hasSettledAmount ? settledAmountMinor! : getEtbFare(i),
currency: voucherCurrency,
fareIsMajorUnits: hasSettledAmount,
createdAt,
});
}

View File

@@ -24,8 +24,11 @@ interface PassengerVoucherData {
dateOfBirth?: string;
nationality?: string;
seatNumber?: string;
coachNumber?: string;
outboundSeatNumber?: string;
outboundCoachNumber?: string;
inboundSeatNumber?: string;
inboundCoachNumber?: string;
status: string;
outboundSchedule: ScheduleInfo;
inboundSchedule?: ScheduleInfo;
@@ -314,16 +317,21 @@ function drawPassengerDetails(doc: jsPDF, data: PassengerVoucherData, y: number,
label(doc, 'Passenger details', margin, y);
y += 7;
const formatSeat = (coach: string | undefined, seat: string | undefined): string => {
if (!seat) return '—';
return coach ? `Coach ${coach} · Seat ${seat}` : `Seat ${seat}`;
};
const rows: [string, string][] = [
['Full name', data.passengerName || '—'],
['Date of birth', data.dateOfBirth ? new Date(data.dateOfBirth).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }) : '—'],
['Nationality', data.nationality || '—'],
];
if (data.isRoundTrip) {
rows.push(['Outbound seat', data.outboundSeatNumber || '—']);
rows.push(['Return seat', data.inboundSeatNumber || '—']);
rows.push(['Outbound seat', formatSeat(data.outboundCoachNumber, data.outboundSeatNumber)]);
rows.push(['Return seat', formatSeat(data.inboundCoachNumber, data.inboundSeatNumber)]);
} else {
rows.push(['Seat', data.seatNumber || '—']);
rows.push(['Seat', formatSeat(data.coachNumber, data.seatNumber)]);
}
const rowH = 7;
@@ -485,9 +493,10 @@ export const generateVoucherPDF = async (booking: VoucherData): Promise<void> =>
// Group leg rows back into one entry per real passenger — without this, a round trip
// produced two half-passenger vouchers (one per leg, each showing only its own leg's
// seat) instead of one voucher per passenger covering both legs.
type SeatInfo = VoucherData['passengers'][number]['seat'];
const grouped = new Map<
string,
{ fullName: string; category: string; outboundSeat?: VoucherData['passengers'][number]['seat']; returnSeat?: VoucherData['passengers'][number]['seat'] }
{ fullName: string; category: string; outboundSeat?: SeatInfo; returnSeat?: SeatInfo }
>();
booking.passengers.forEach((p) => {
const key = `${p.fullName}|${p.dateOfBirth}|${p.category}`;
@@ -514,20 +523,23 @@ export const generateVoucherPDF = async (booking: VoucherData): Promise<void> =>
const ticketNumber = matchedTicket?.barcodePayload || 'Not yet issued';
await generatePassengerVoucherPDF({
bookingRef: booking.bookingRef,
bookingRef: booking.bookingRef,
ticketNumber,
passengerName: p.fullName,
status: booking.status,
outboundSchedule: { ...booking.schedule, seatClass: p.outboundSeat?.seatClass },
inboundSchedule: isRoundTrip ? { ...booking.returnSchedule!, seatClass: p.returnSeat?.seatClass } : undefined,
passengerName: p.fullName,
status: booking.status,
outboundSchedule: { ...booking.schedule, seatClass: p.outboundSeat?.seatClass },
inboundSchedule: isRoundTrip ? { ...booking.returnSchedule!, seatClass: p.returnSeat?.seatClass } : undefined,
isRoundTrip,
seatNumber: isRoundTrip ? undefined : p.outboundSeat?.number,
outboundSeatNumber: isRoundTrip ? p.outboundSeat?.number : undefined,
inboundSeatNumber: isRoundTrip ? p.returnSeat?.number : undefined,
fareMinor: voucherFareMinor,
currency: voucherCurrency,
fareIsMajorUnits: useSettledAmount,
createdAt: booking.createdAt,
seatNumber: isRoundTrip ? undefined : p.outboundSeat?.number,
coachNumber: isRoundTrip ? undefined : p.outboundSeat?.coach,
outboundSeatNumber: isRoundTrip ? p.outboundSeat?.number : undefined,
outboundCoachNumber: isRoundTrip ? p.outboundSeat?.coach : undefined,
inboundSeatNumber: isRoundTrip ? p.returnSeat?.number : undefined,
inboundCoachNumber: isRoundTrip ? p.returnSeat?.coach : undefined,
fareMinor: voucherFareMinor,
currency: voucherCurrency,
fareIsMajorUnits: useSettledAmount,
createdAt: booking.createdAt,
});
}
};