ti2-tourplan 1.0.52 → 1.0.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +119 -16
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -193,7 +193,7 @@ class Plugin {
193
193
  // add one RoomConfig for each room required (i.e. one for each PaxConfig)
194
194
  RoomConfigs.RoomConfig = [];
195
195
  let indexRoomConfig = 0;
196
- paxConfigs.map(({ roomType, passengers = [] }) => {
196
+ paxConfigs.forEach(({ roomType, passengers = [] }) => {
197
197
  const EachRoomConfig = passengers.reduce((acc, p) => {
198
198
  console.log(JSON.stringify(p));
199
199
  if (p.passengerType === 'Adult') {
@@ -223,9 +223,21 @@ class Plugin {
223
223
  if (passengers && passengers.length && !noPaxList) {
224
224
  // There should be only 1 PaxList inside each EachRoomConfig
225
225
  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
+ }
229
241
  const EachPaxDetails = {
230
242
  Forename: this.escapeInvalidXmlChars(p.firstName),
231
243
  Surname: this.escapeInvalidXmlChars(p.lastName),
@@ -242,7 +254,7 @@ class Plugin {
242
254
  EachPaxDetails.Age = p.age;
243
255
  }
244
256
  }
245
- EachRoomConfig.PaxList.PaxDetails[indexEachPax] = EachPaxDetails;
257
+ return EachPaxDetails;
246
258
  });
247
259
  }
248
260
  RoomConfigs.RoomConfig[indexRoomConfig++] = EachRoomConfig
@@ -703,10 +715,21 @@ class Plugin {
703
715
  puInfo,
704
716
  doInfo,
705
717
  notes,
718
+ QB,
706
719
  directHeaderPayload,
707
720
  directLinePayload,
721
+ customFieldValues = [],
708
722
  },
709
723
  }) {
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
+ }, {});
710
733
  const model = {
711
734
  AddServiceRequest: {
712
735
  AgentID: hostConnectAgentID,
@@ -716,7 +739,7 @@ class Plugin {
716
739
  } : {
717
740
  NewBookingInfo: {
718
741
  Name: this.escapeInvalidXmlChars(quoteName),
719
- QB: 'Q',
742
+ QB: QB || 'Q',
720
743
  ...(directHeaderPayload || {}),
721
744
  },
722
745
  }),
@@ -757,6 +780,7 @@ class Plugin {
757
780
  AgentRef: reference,
758
781
  RoomConfigs: this.getRoomConfigs(paxConfigs),
759
782
  ...(directLinePayload || {}),
783
+ ...(cfvPerService || {}),
760
784
  },
761
785
  };
762
786
  const replyObj = await this.callTourplan({
@@ -769,7 +793,7 @@ class Plugin {
769
793
  message: R.path(['AddServiceReply', 'Status'], replyObj)
770
794
  === 'NO' ? 'Service cannot be added to quote for the requested date/stay. (e.g. no rates, block out period, on request, minimum stay etc.)' : '',
771
795
  quote: {
772
- id: R.path(['AddServiceReply', 'BookingId'], replyObj),
796
+ id: R.path(['AddServiceReply', 'BookingId'], replyObj) || quoteId,
773
797
  reference: R.path(['AddServiceReply', 'Ref'], replyObj),
774
798
  linePrice: R.path(['AddServiceReply', 'Services', 'Service', 'LinePrice'], replyObj),
775
799
  lineId: R.path(['AddServiceReply', 'ServiceLineId'], replyObj),
@@ -779,14 +803,38 @@ class Plugin {
779
803
 
780
804
  // eslint-disable-next-line class-methods-use-this
781
805
  async getCreateBookingFields({
782
- // token: {
783
- // hostConnectAgentID,
784
- // hostConnectAgentPassword,
785
- // hostConnectEndpoint,
786
- // },
787
- // axios,
806
+ token: {
807
+ hostConnectAgentID,
808
+ hostConnectAgentPassword,
809
+ hostConnectEndpoint,
810
+ },
811
+ axios,
788
812
  }) {
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
+ }];
790
838
  return {
791
839
  fields: [],
792
840
  customFields,
@@ -866,13 +914,68 @@ class Plugin {
866
914
  const getBookingPayload = getPayload('GetBookingRequest', {
867
915
  BookingId: R.prop('BookingId', bookingHeader),
868
916
  ReturnAccountInfo: 'Y',
917
+ ReturnRoomConfigs: 'Y',
869
918
  });
870
919
  const bookingReply = await this.callTourplan(getBookingPayload);
871
920
  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
+ });
873
976
  return {
874
977
  ...booking,
875
- Services: Array.isArray(Services) ? Services : [Services],
978
+ Services,
876
979
  };
877
980
  }, { concurrency: 10 });
878
981
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ti2-tourplan",
3
- "version": "1.0.52",
3
+ "version": "1.0.53",
4
4
  "description": "Tourplan's TI2 Plugin",
5
5
  "main": "index.js",
6
6
  "scripts": {