Skip to content

Commit 877350f

Browse files
authored
Merge pull request #26 from TourConnect/feat/dupe_pax_n_location_code
Feat/dupe pax n location code
2 parents 1fa4538 + 4864c75 commit 877350f

File tree

1 file changed

+119
-16
lines changed

1 file changed

+119
-16
lines changed

index.js

Lines changed: 119 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ class Plugin {
193193
// add one RoomConfig for each room required (i.e. one for each PaxConfig)
194194
RoomConfigs.RoomConfig = [];
195195
let indexRoomConfig = 0;
196-
paxConfigs.map(({ roomType, passengers = [] }) => {
196+
paxConfigs.forEach(({ roomType, passengers = [] }) => {
197197
const EachRoomConfig = passengers.reduce((acc, p) => {
198198
console.log(JSON.stringify(p));
199199
if (p.passengerType === 'Adult') {
@@ -223,9 +223,21 @@ class Plugin {
223223
if (passengers && passengers.length && !noPaxList) {
224224
// There should be only 1 PaxList inside each EachRoomConfig
225225
EachRoomConfig.PaxList = {};
226-
// Inside PaxList, there should be 1 PaxDetails for each passenger (Pax)
227-
EachRoomConfig.PaxList.PaxDetails = [];
228-
passengers.forEach((p, indexEachPax) => {
226+
// Inside PaxList, there should be 1 PaxDetail for each passenger (Pax)
227+
EachRoomConfig.PaxList.PaxDetails = passengers.map(p => {
228+
/*
229+
TP API doesn't allow us to modify existing pax details
230+
when PersonId is present, other details are ignored by TP anyways
231+
when it is not present, TP is comparing every key in PaxDetail to identify
232+
duplicate, so if we send Pax Detail with the same first and last name, but different
233+
Age, TP will consider them to be different pax, which actually is duplicate, given
234+
sometimes AI could be extracting inconsistent data
235+
*/
236+
if (p.personId) {
237+
return {
238+
PersonId: p.personId,
239+
};
240+
}
229241
const EachPaxDetails = {
230242
Forename: this.escapeInvalidXmlChars(p.firstName),
231243
Surname: this.escapeInvalidXmlChars(p.lastName),
@@ -242,7 +254,7 @@ class Plugin {
242254
EachPaxDetails.Age = p.age;
243255
}
244256
}
245-
EachRoomConfig.PaxList.PaxDetails[indexEachPax] = EachPaxDetails;
257+
return EachPaxDetails;
246258
});
247259
}
248260
RoomConfigs.RoomConfig[indexRoomConfig++] = EachRoomConfig
@@ -703,10 +715,21 @@ class Plugin {
703715
puInfo,
704716
doInfo,
705717
notes,
718+
QB,
706719
directHeaderPayload,
707720
directLinePayload,
721+
customFieldValues = [],
708722
},
709723
}) {
724+
const cfvPerService = customFieldValues.filter(f => f.isPerService && f.value)
725+
.reduce((acc, f) => {
726+
if (f.type === 'extended-option') {
727+
acc[f.id] = f.value.value || f.value;
728+
} else {
729+
acc[f.id] = f.value;
730+
}
731+
return acc;
732+
}, {});
710733
const model = {
711734
AddServiceRequest: {
712735
AgentID: hostConnectAgentID,
@@ -716,7 +739,7 @@ class Plugin {
716739
} : {
717740
NewBookingInfo: {
718741
Name: this.escapeInvalidXmlChars(quoteName),
719-
QB: 'Q',
742+
QB: QB || 'Q',
720743
...(directHeaderPayload || {}),
721744
},
722745
}),
@@ -757,6 +780,7 @@ class Plugin {
757780
AgentRef: reference,
758781
RoomConfigs: this.getRoomConfigs(paxConfigs),
759782
...(directLinePayload || {}),
783+
...(cfvPerService || {}),
760784
},
761785
};
762786
const replyObj = await this.callTourplan({
@@ -769,7 +793,7 @@ class Plugin {
769793
message: R.path(['AddServiceReply', 'Status'], replyObj)
770794
=== 'NO' ? 'Service cannot be added to quote for the requested date/stay. (e.g. no rates, block out period, on request, minimum stay etc.)' : '',
771795
quote: {
772-
id: R.path(['AddServiceReply', 'BookingId'], replyObj),
796+
id: R.path(['AddServiceReply', 'BookingId'], replyObj) || quoteId,
773797
reference: R.path(['AddServiceReply', 'Ref'], replyObj),
774798
linePrice: R.path(['AddServiceReply', 'Services', 'Service', 'LinePrice'], replyObj),
775799
lineId: R.path(['AddServiceReply', 'ServiceLineId'], replyObj),
@@ -779,14 +803,38 @@ class Plugin {
779803

780804
// eslint-disable-next-line class-methods-use-this
781805
async getCreateBookingFields({
782-
// token: {
783-
// hostConnectAgentID,
784-
// hostConnectAgentPassword,
785-
// hostConnectEndpoint,
786-
// },
787-
// axios,
806+
token: {
807+
hostConnectAgentID,
808+
hostConnectAgentPassword,
809+
hostConnectEndpoint,
810+
},
811+
axios,
788812
}) {
789-
const customFields = [];
813+
const model = {
814+
GetLocationsRequest: {
815+
AgentID: hostConnectAgentID,
816+
Password: hostConnectAgentPassword,
817+
},
818+
};
819+
const GetLocationsReply = await this.cache.getOrExec({
820+
fnParams: [model],
821+
fn: () => this.callTourplan({
822+
model,
823+
endpoint: hostConnectEndpoint,
824+
axios,
825+
xmlOptions: hostConnectXmlOptions,
826+
}),
827+
ttl: 60 * 60 * 12, // 2 hours
828+
});
829+
let locationCodes = R.pathOr([], ['GetLocationsReply', 'Locations', 'Location'], GetLocationsReply);
830+
if (!Array.isArray(locationCodes)) locationCodes = [locationCodes];
831+
const customFields = [{
832+
id: 'LocationCode',
833+
label: 'Location Code',
834+
type: 'extended-option',
835+
isPerService: true,
836+
options: locationCodes.map(o => ({ value: o.Code, label: `${o.Name} (${o.Code})` })),
837+
}];
790838
return {
791839
fields: [],
792840
customFields,
@@ -866,13 +914,68 @@ class Plugin {
866914
const getBookingPayload = getPayload('GetBookingRequest', {
867915
BookingId: R.prop('BookingId', bookingHeader),
868916
ReturnAccountInfo: 'Y',
917+
ReturnRoomConfigs: 'Y',
869918
});
870919
const bookingReply = await this.callTourplan(getBookingPayload);
871920
const booking = R.path(['GetBookingReply'], bookingReply);
872-
const Services = R.pathOr([], ['Services', 'Service'], booking);
921+
/*
922+
booking = {
923+
Services: {
924+
...
925+
RoomConfigs: {
926+
RoomConfig: {
927+
Adults: '2',
928+
Children: '0',
929+
Infants: '0',
930+
PaxList: {
931+
PaxDetails: [
932+
{
933+
Age: '37',
934+
DateOfBirth: '1987-09-26',
935+
Forename: 'Chris',
936+
PaxType: 'A',
937+
PersonId: '628206',
938+
Surname: 'Voss'
939+
},
940+
{
941+
Age: '36',
942+
DateOfBirth: '1988-09-26',
943+
Forename: 'Joy',
944+
PaxType: 'A',
945+
PersonId: '628207',
946+
Surname: 'Voss'
947+
}
948+
]
949+
}
950+
}
951+
},
952+
...
953+
}
954+
}
955+
*/
956+
let Services = R.pathOr([], ['Services', 'Service'], booking);
957+
if (!Array.isArray(Services)) Services = [Services];
958+
Services = Services.map(s => {
959+
let actualRoomConfigs = s.RoomConfigs.RoomConfig;
960+
if (!Array.isArray(actualRoomConfigs)) actualRoomConfigs = [actualRoomConfigs];
961+
const paxList = actualRoomConfigs.reduce((acc, roomConfig) => {
962+
const paxDetails = R.pathOr([], ['PaxList', 'PaxDetails'], roomConfig);
963+
if (!Array.isArray(paxDetails)) return acc;
964+
return [...acc, ...paxDetails];
965+
}, [])
966+
.map(p => ({
967+
personId: R.path(['PersonId'], p),
968+
firstName: R.path(['Forename'], p),
969+
lastName: R.path(['Surname'], p),
970+
}));
971+
return {
972+
...s,
973+
paxList,
974+
};
975+
});
873976
return {
874977
...booking,
875-
Services: Array.isArray(Services) ? Services : [Services],
978+
Services,
876979
};
877980
}, { concurrency: 10 });
878981
return {

0 commit comments

Comments
 (0)