From 25f2cd81927aa3b4e55dcae8f04fe62d74e321c6 Mon Sep 17 00:00:00 2001 From: Maurice Date: Fri, 6 Nov 2026 23:50:53 +0100 Subject: [PATCH] fix(booking-import): every leg of a connecting flight keeps its own seat The grouped flight wrote a seat only on the booking itself, from the first segment. Each leg in metadata.legs now carries the seat of its own segment, which the planner and the PDF already show per leg. --- .../nest/booking-import/kitinerary-mapper.ts | 2 ++ .../booking-import/kitineraryMapper.test.ts | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/server/src/nest/booking-import/kitinerary-mapper.ts b/server/src/nest/booking-import/kitinerary-mapper.ts index 7fdf9c100..4504f76a3 100644 --- a/server/src/nest/booking-import/kitinerary-mapper.ts +++ b/server/src/nest/booking-import/kitinerary-mapper.ts @@ -304,11 +304,13 @@ function mapFlightGroup(legs: KiReservation[], source: ParsedBookingItem['source const arrEp = makeEndpoint(f.arrivalAirport, isLast ? 'to' : 'stop', onward.time, onward.date); if (arrEp) endpoints.push(arrEp); const airline = f.airline?.name ?? f.airline?.iataCode ?? ''; + const { seat } = segmentDetail(legs[i]); metaLegs.push({ from: iataOf(f.departureAirport), to: iataOf(f.arrivalAirport), ...(airline ? { airline } : {}), ...(f.flightNumber ? { flight_number: f.flightNumber } : {}), + ...(seat != null ? { seat } : {}), dep_time: splitIso(f.departureTime).time, arr_time: arr.time, }); diff --git a/server/tests/unit/nest/booking-import/kitineraryMapper.test.ts b/server/tests/unit/nest/booking-import/kitineraryMapper.test.ts index eac174312..71d5db5e8 100644 --- a/server/tests/unit/nest/booking-import/kitineraryMapper.test.ts +++ b/server/tests/unit/nest/booking-import/kitineraryMapper.test.ts @@ -654,3 +654,30 @@ describe('kitinerary mapper: the seat as KItinerary writes it', () => { expect(items[0].metadata).toMatchObject({ seat: '23A' }); }); }); + +describe('kitinerary mapper: the seat on each leg of a connecting flight', () => { + it('keeps every leg its own seat', () => { + const { items } = mapReservations( + legs( + { ...flight('ABC123', FRA, BER, '2026-06-11T10:00:00', '2026-06-11T12:00:00', 'LH 100'), airplaneSeat: '12C' }, + { ...flight('ABC123', BER, HND, '2026-06-11T14:30:00', '2026-06-11T23:30:00', 'LH 200'), airplaneSeat: '40A' }, + ), + 'test.json', + ); + const legsMeta = (items[0].metadata as { legs: { seat?: string }[] }).legs; + expect(legsMeta.map((leg) => leg.seat)).toEqual(['12C', '40A']); + }); + + it('leaves the seat off a leg that has none', () => { + const { items } = mapReservations( + legs(flight('ABC123', FRA, BER, '2026-06-11T10:00:00', '2026-06-11T12:00:00', 'LH 100'), { + ...flight('ABC123', BER, HND, '2026-06-11T14:30:00', '2026-06-11T23:30:00', 'LH 200'), + airplaneSeat: '40A', + }), + 'test.json', + ); + const legsMeta = (items[0].metadata as { legs: Record[] }).legs; + expect(legsMeta[0]).not.toHaveProperty('seat'); + expect(legsMeta[1]).toMatchObject({ seat: '40A' }); + }); +});