ti2-tourplan 1.0.51 → 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 +121 -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,9 +715,21 @@ class Plugin {
703
715
  puInfo,
704
716
  doInfo,
705
717
  notes,
718
+ QB,
706
719
  directHeaderPayload,
720
+ directLinePayload,
721
+ customFieldValues = [],
707
722
  },
708
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
+ }, {});
709
733
  const model = {
710
734
  AddServiceRequest: {
711
735
  AgentID: hostConnectAgentID,
@@ -715,7 +739,7 @@ class Plugin {
715
739
  } : {
716
740
  NewBookingInfo: {
717
741
  Name: this.escapeInvalidXmlChars(quoteName),
718
- QB: 'Q',
742
+ QB: QB || 'Q',
719
743
  ...(directHeaderPayload || {}),
720
744
  },
721
745
  }),
@@ -755,6 +779,8 @@ class Plugin {
755
779
  })(),
756
780
  AgentRef: reference,
757
781
  RoomConfigs: this.getRoomConfigs(paxConfigs),
782
+ ...(directLinePayload || {}),
783
+ ...(cfvPerService || {}),
758
784
  },
759
785
  };
760
786
  const replyObj = await this.callTourplan({
@@ -767,7 +793,7 @@ class Plugin {
767
793
  message: R.path(['AddServiceReply', 'Status'], replyObj)
768
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.)' : '',
769
795
  quote: {
770
- id: R.path(['AddServiceReply', 'BookingId'], replyObj),
796
+ id: R.path(['AddServiceReply', 'BookingId'], replyObj) || quoteId,
771
797
  reference: R.path(['AddServiceReply', 'Ref'], replyObj),
772
798
  linePrice: R.path(['AddServiceReply', 'Services', 'Service', 'LinePrice'], replyObj),
773
799
  lineId: R.path(['AddServiceReply', 'ServiceLineId'], replyObj),
@@ -777,14 +803,38 @@ class Plugin {
777
803
 
778
804
  // eslint-disable-next-line class-methods-use-this
779
805
  async getCreateBookingFields({
780
- // token: {
781
- // hostConnectAgentID,
782
- // hostConnectAgentPassword,
783
- // hostConnectEndpoint,
784
- // },
785
- // axios,
806
+ token: {
807
+ hostConnectAgentID,
808
+ hostConnectAgentPassword,
809
+ hostConnectEndpoint,
810
+ },
811
+ axios,
786
812
  }) {
787
- 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
+ }];
788
838
  return {
789
839
  fields: [],
790
840
  customFields,
@@ -864,13 +914,68 @@ class Plugin {
864
914
  const getBookingPayload = getPayload('GetBookingRequest', {
865
915
  BookingId: R.prop('BookingId', bookingHeader),
866
916
  ReturnAccountInfo: 'Y',
917
+ ReturnRoomConfigs: 'Y',
867
918
  });
868
919
  const bookingReply = await this.callTourplan(getBookingPayload);
869
920
  const booking = R.path(['GetBookingReply'], bookingReply);
870
- 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
+ });
871
976
  return {
872
977
  ...booking,
873
- Services: Array.isArray(Services) ? Services : [Services],
978
+ Services,
874
979
  };
875
980
  }, { concurrency: 10 });
876
981
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ti2-tourplan",
3
- "version": "1.0.51",
3
+ "version": "1.0.53",
4
4
  "description": "Tourplan's TI2 Plugin",
5
5
  "main": "index.js",
6
6
  "scripts": {