mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-30 18:46:00 +00:00
fix(airtrail): import the airline name, not the ICAO code (#1334)
AirTrail returns each airline as {icao, iata, name}, but the import reduced it to the ICAO/IATA code, so an imported flight showed e.g. 'EWG' instead of 'Eurowings'. The picker and the stored reservation now use the airline name (falling back to the code when AirTrail has none). The raw code is kept in metadata.airline_code so the writeback to AirTrail still sends a code, not a name (#1240), and the change-detection snapshot hash stays on the code so existing flights don't spuriously re-sync.
This commit is contained in:
@@ -15,6 +15,15 @@ export function entityCode(e: AirtrailNamedCode | null | undefined): string | nu
|
||||
return e?.icao || e?.iata || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Human-readable name for an airline/aircraft (e.g. "Lufthansa"), falling back to the
|
||||
* code when AirTrail doesn't provide a name. Used for what TREK displays/stores; the
|
||||
* raw code stays available via entityCode for the writeback payload (#1334).
|
||||
*/
|
||||
export function entityName(e: AirtrailNamedCode | null | undefined): string | null {
|
||||
return e?.name || e?.icao || e?.iata || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local calendar date + clock time for an instant at a given IANA zone.
|
||||
* AirTrail stores `departure`/`arrival` as instants (ISO w/ offset) plus a local
|
||||
@@ -57,7 +66,7 @@ export function normalizeFlight(raw: AirtrailFlightRaw): AirtrailFlight {
|
||||
date: raw.date ?? null,
|
||||
departure: raw.departureScheduled ?? null,
|
||||
arrival: raw.arrivalScheduled ?? null,
|
||||
airline: entityCode(raw.airline),
|
||||
airline: entityName(raw.airline),
|
||||
flightNumber: raw.flightNumber ?? null,
|
||||
aircraft: entityCode(raw.aircraft),
|
||||
seatClass: (raw.seats?.find(s => s.userId) ?? raw.seats?.[0])?.seatClass ?? null,
|
||||
@@ -142,10 +151,14 @@ export function mapFlightToReservation(raw: AirtrailFlightRaw): MappedReservatio
|
||||
}
|
||||
|
||||
const seat = raw.seats?.find(s => s.userId) ?? raw.seats?.[0];
|
||||
const airlineName = entityName(raw.airline);
|
||||
const airlineCode = entityCode(raw.airline);
|
||||
const aircraftCode = entityCode(raw.aircraft);
|
||||
const metadata: Record<string, unknown> = {};
|
||||
if (airlineCode) metadata.airline = airlineCode;
|
||||
// Display the airline name; keep the code in airline_code for the AirTrail writeback,
|
||||
// which expects a code, not a name (#1334 / #1240).
|
||||
if (airlineName) metadata.airline = airlineName;
|
||||
if (airlineCode) metadata.airline_code = airlineCode;
|
||||
if (raw.flightNumber) metadata.flight_number = raw.flightNumber;
|
||||
if (aircraftCode) metadata.aircraft = aircraftCode;
|
||||
if (raw.aircraftReg) metadata.aircraft_reg = raw.aircraftReg;
|
||||
|
||||
@@ -216,9 +216,10 @@ export function buildSavePayload(reservation: any, existing: AirtrailFlightRaw):
|
||||
arrivalScheduledTime: arr.time,
|
||||
// These are AirTrail-owned details TREK doesn't surface in its edit UI — a TREK
|
||||
// edit can leave them out of `metadata`. Preserve AirTrail's current value when
|
||||
// TREK has none rather than nulling it out (#1240). entityCode mirrors the
|
||||
// TREK has none rather than nulling it out (#1240). Use airline_code (not the
|
||||
// display name in metadata.airline, #1334); both it and entityCode mirror the
|
||||
// import/hash code-selection so a writeback stays a no-op for the hash.
|
||||
airline: meta.airline ?? entityCode(existing.airline) ?? null,
|
||||
airline: meta.airline_code ?? entityCode(existing.airline) ?? null,
|
||||
flightNumber: meta.flight_number ?? existing.flightNumber ?? null,
|
||||
aircraft: meta.aircraft ?? entityCode(existing.aircraft) ?? null,
|
||||
aircraftReg: meta.aircraft_reg ?? existing.aircraftReg ?? null,
|
||||
|
||||
@@ -47,7 +47,7 @@ describe('airtrailMapper.normalizeFlight', () => {
|
||||
fromCode: 'JFK',
|
||||
toCode: 'LHR',
|
||||
date: '2021-09-01',
|
||||
airline: 'BAW',
|
||||
airline: 'British Airways',
|
||||
flightNumber: 'BA178',
|
||||
seatClass: 'economy',
|
||||
});
|
||||
@@ -98,12 +98,19 @@ describe('airtrailMapper.mapFlightToReservation', () => {
|
||||
|
||||
it('carries flight metadata', () => {
|
||||
const m = mapFlightToReservation(flight());
|
||||
expect(m.metadata).toMatchObject({ airline: 'BAW', flight_number: 'BA178', aircraft: 'B772', aircraft_reg: 'G-VIIL', flight_reason: 'leisure', seat: '12A' });
|
||||
// #1334: display the airline name, keep the code in airline_code for the writeback.
|
||||
expect(m.metadata).toMatchObject({ airline: 'British Airways', airline_code: 'BAW', flight_number: 'BA178', aircraft: 'B772', aircraft_reg: 'G-VIIL', flight_reason: 'leisure', seat: '12A' });
|
||||
expect(m.type).toBe('flight');
|
||||
expect(m.status).toBe('confirmed');
|
||||
expect(m.notes).toBe('window seat');
|
||||
});
|
||||
|
||||
it('#1334 falls back to the airline code when AirTrail provides no name', () => {
|
||||
const a = { id: 9, icao: 'EWG', iata: 'EW' };
|
||||
expect(normalizeFlight(flight({ airline: a })).airline).toBe('EWG');
|
||||
expect(mapFlightToReservation(flight({ airline: a })).metadata).toMatchObject({ airline: 'EWG', airline_code: 'EWG' });
|
||||
});
|
||||
|
||||
it('uses only the seat number for the seat, not the cabin class (#1246)', () => {
|
||||
// AirTrail often has a class but no seat number until check-in; the class
|
||||
// must not leak into the seat field.
|
||||
|
||||
Reference in New Issue
Block a user