Skip to content

Commit 9f2806d

Browse files
authored
feat(booking): add new fields to passenger data (#258)
- add new loyalty programme fields to the OfferRequestPassenger interface and validate - add unit test
1 parent 6d522f7 commit 9f2806d

4 files changed

Lines changed: 98 additions & 2 deletions

File tree

src/booking/OfferRequests/OfferRequests.spec.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import nock from 'nock'
22
import { Client } from '../../Client'
3+
import { CreateOfferRequest } from './OfferRequestsTypes'
34
import { mockCreateOfferRequest, mockOfferRequest } from './mockOfferRequest'
45
import { OfferRequests } from './OfferRequests'
56

@@ -49,6 +50,42 @@ describe('OfferRequests', () => {
4950
expect(response.data?.id).toBe(mockOfferRequest.id)
5051
})
5152

53+
test('should create an offer request and return an offer with passenger loyalty programme details', async () => {
54+
const passengersWithLoyaltyProgrammes: CreateOfferRequest['passengers'] = [
55+
{
56+
type: 'adult',
57+
given_name: 'Tony',
58+
family_name: 'Stark',
59+
loyalty_programme_accounts: [
60+
{
61+
account_number: '12901014',
62+
airline_iata_code: 'BA'
63+
}
64+
],
65+
},
66+
]
67+
68+
const mockResponseWithLoyaltyProgrammes = {
69+
...mockOfferRequest,
70+
passengers: [
71+
{
72+
...passengersWithLoyaltyProgrammes[0],
73+
id: 'pas_0000AD3shfu6ubXmZr5R1H'
74+
},
75+
]
76+
}
77+
78+
nock(/(.*)/)
79+
.post('/air/offer_requests/')
80+
.reply(200, { data: mockResponseWithLoyaltyProgrammes })
81+
82+
const response = await new OfferRequests(new Client({ token: 'mockToken' })).create({
83+
...mockCreateOfferRequest,
84+
passengers: passengersWithLoyaltyProgrammes
85+
})
86+
expect(response.data?.passengers[0].loyalty_programme_accounts).toHaveLength(1)
87+
})
88+
5289
test('should create an offer request and no offers should return when requested', async () => {
5390
const mockResponseWithoutOffer = { ...mockOfferRequest }
5491
delete mockResponseWithoutOffer.offers

src/booking/OfferRequests/OfferRequests.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {
44
CreateOfferRequestQueryParameters,
55
DuffelResponse,
66
OfferRequest,
7-
PaginationMeta
7+
PaginationMeta,
8+
ValidationError
89
} from '../../types'
910

1011
/**
@@ -60,6 +61,17 @@ export class OfferRequests extends Resource {
6061
options: Partial<CreateOfferRequest & CreateOfferRequestQueryParameters>
6162
): Promise<DuffelResponse<OfferRequest>> => {
6263
const { return_offers, ...data } = options
64+
65+
data.passengers && data.passengers.forEach(passenger => {
66+
if (
67+
passenger.loyalty_programme_accounts
68+
&& passenger.loyalty_programme_accounts.length > 0
69+
&& (!passenger.given_name || !passenger.family_name)
70+
) {
71+
throw new ValidationError('loyalty programme requires family_name and given_name parameters')
72+
}
73+
})
74+
6375
return this.request({
6476
method: 'POST',
6577
path: `${this.path}/`,

src/booking/OfferRequests/OfferRequestsTypes.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CabinClass, Place, PlaceType } from '../../types'
1+
import { Airline, CabinClass, Place, PlaceType } from '../../types'
22
import { Offer } from '../Offers/OfferTypes'
33

44
export interface OfferRequestSlice {
@@ -42,6 +42,31 @@ export interface OfferRequestPassenger {
4242
*/
4343
type?: 'adult'
4444

45+
/**
46+
* The passenger's family name. Only `space`, `-`, `'`, and letters from the `ASCII`, `Latin-1 Supplement` and `Latin
47+
* Extended-A` (with the exceptions of `Æ`, `æ`, `IJ`, `ij`, `Œ`, `œ`, `Þ`, , and `ð`) Unicode charts are accepted. All
48+
* other characters will result in a validation error. The minimum length is 1 character, and the maximum is 20
49+
* characters.
50+
*
51+
* This is only required if you're also including **Loyalty Programme Accounts**.
52+
*/
53+
family_name?: string
54+
55+
/**
56+
* The passenger's given name. Only `space`, `-`, `'`, and letters from the `ASCII`, `Latin-1 Supplement` and `Latin
57+
* Extended-A` (with the exceptions of `Æ`, `æ`, `IJ`, `ij`, `Œ`, `œ`, `Þ`, , and `ð`) Unicode charts are accepted. All
58+
* other characters will result in a validation error. The minimum length is 1 character, and the maximum is 20
59+
* characters.
60+
*
61+
* This is only required if you're also including **Loyalty Programme Accounts**.
62+
*/
63+
given_name?: string
64+
65+
/**
66+
* The **Loyalty Programme Accounts** for this passenger.
67+
*/
68+
loyalty_programme_accounts?: LoyaltyProgrammeAccount[]
69+
4570
/**
4671
* The identifier for the passenger, unique within this Offer Request and across all Offer Requests.
4772
* This ID will be generated by Duffel unless you had optionally provided one.
@@ -50,6 +75,21 @@ export interface OfferRequestPassenger {
5075
id: string
5176
}
5277

78+
/**
79+
* The **Loyalty Programme Account** details.
80+
*/
81+
export interface LoyaltyProgrammeAccount {
82+
/**
83+
* The passenger's account number for this **Loyalty Programme Account**.
84+
*/
85+
account_number: string
86+
87+
/**
88+
* The IATA code for the airline that this **Loyalty Programme Account** belongs to.
89+
*/
90+
airline_iata_code: Airline['iata_code']
91+
}
92+
5393
/**
5494
* To search for flights, you'll need to create an offer request.
5595
* An offer request describes the passengers and where and when they want to travel (in the form of a list of slices).

src/types/ClientType.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ export class DuffelError extends Error {
8686
}
8787
}
8888

89+
export class ValidationError extends Error {
90+
constructor(message: string) {
91+
super('Invalid data: ' + message)
92+
this.name = "ValidationError";
93+
}
94+
}
95+
8996
export interface SDKOptions {
9097
/**
9198
* If `true` it will output the path and the method called

0 commit comments

Comments
 (0)