ti2-tourplan 1.0.41 → 1.0.42

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 +60 -54
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -170,13 +170,14 @@ class Plugin {
170
170
  }
171
171
  const requestType = R.keys(model)[0];
172
172
  if (!replyObj) throw new Error(`${requestType} failed: ${errorStr || 'no reply object'}`);
173
- const error = replyObj.error || R.path(['Reply', 'ErrorReply', 'Error'], replyObj);
173
+ let error = replyObj.error || R.path(['Reply', 'ErrorReply', 'Error'], replyObj);
174
174
  if (error) {
175
- if (error.indexOf('2050 SCN Request denied for TEST connecting from') > -1
176
- && requestType === 'OptionInfoRequest'
177
- && endpoint.indexOf('actour') > -1
178
- ) {
179
- return 'useFixture';
175
+ if (error.includes('DateFrom in the past')) {
176
+ error = '1002 - Date is in the past';
177
+ } else if (error.includes('1052 SCN')) {
178
+ error = '1052 - OptionId not found(Check if it is Internet Enabled)';
179
+ } else if (error.includes('SCN Server overloaded')) {
180
+ error = "2051 - The Tourplan server is unavailable. Please wait a minute and try again. If you keep getting this error, please contact your team's Tourplan administrator or Tourplan support."
180
181
  }
181
182
  throw new Error(`${requestType} failed: ${error}`);
182
183
  }
@@ -442,50 +443,57 @@ class Plugin {
442
443
  xmlOptions: hostConnectXmlOptions,
443
444
  };
444
445
  // use cache if we are getting the full list
445
- const replyObj = await this.callTourplan(payload);
446
- let products = [];
447
- if (replyObj === 'useFixture') {
448
- products = require('./__fixtures__/fullacoptionlist.json');
449
- } else {
450
- products = R.call(R.compose(
451
- R.map(optionsGroupedBySupplierId => {
452
- const OptGeneral = R.pathOr({}, [0, 'OptGeneral'], optionsGroupedBySupplierId);
453
- const supplierData = {
454
- supplierId: R.path(['SupplierId'], OptGeneral),
455
- supplierName: R.path(['SupplierName'], OptGeneral),
456
- supplierAddress: `${R.pathOr('', ['Address1'], OptGeneral)}, ${R.pathOr('', ['Address2'], OptGeneral)}, ${R.pathOr('', ['Address3'], OptGeneral)}, ${R.pathOr('', ['Address4'], OptGeneral)}, ${R.pathOr('', ['Address5'], OptGeneral)}`,
457
- serviceTypes: R.uniq(optionsGroupedBySupplierId.map(R.path(['OptGeneral', 'ButtonName']))),
458
- };
459
- return translateTPOption({
460
- supplierData,
461
- optionsGroupedBySupplierId,
462
- typeDefs: productTypeDefs,
463
- query: productQuery,
464
- });
465
- }),
466
- R.values,
467
- R.groupBy(R.path(['OptGeneral', 'SupplierId'])),
468
- root => {
469
- if (!searchInput) return root;
470
- const getFullSearchStr = o => {
471
- const fullPptionName = `${R.path(['OptGeneral', 'Description'], o) || ''}-${R.path(['OptGeneral', 'Comment'], o) || ''}`;
472
- return `${R.path(['OptGeneral', 'SupplierName'], o) || ''} ${fullPptionName} ${R.path(['Opt'], o)} ${R.path(['OptGeneral', 'SupplierId'], o) || ''}`;
473
- };
474
- const inputValueLower = searchInput.trim().toLowerCase();
475
- const parts = inputValueLower.split(' ').filter(Boolean); // Filter out any empty strings just in case
476
- return root.filter(option => {
477
- const fullSearchStr = getFullSearchStr(option).toLowerCase();
478
- return parts.every(part => fullSearchStr.includes(part));
479
- });
480
- },
481
- root => {
482
- const options = R.pathOr([], ['OptionInfoReply', 'Option'], root);
483
- // due to the new parser, single option will be returned as an object
484
- // instead of an array
485
- if (Array.isArray(options)) return options;
486
- return [options];
487
- },
488
- ), replyObj);
446
+ // for example: for searchInput (backend search), we shouldn't get the full list from
447
+ // tourplan each time user search
448
+ const replyObj = optionId
449
+ ? await this.callTourplan(payload)
450
+ : await this.cache.getOrExec({
451
+ fnParams: [model],
452
+ fn: () => this.callTourplan(payload),
453
+ ttl: 60 * 60 * 2, // 2 hours
454
+ forceRefresh: Boolean(forceRefresh),
455
+ });
456
+ const products = R.call(R.compose(
457
+ R.map(optionsGroupedBySupplierId => {
458
+ const OptGeneral = R.pathOr({}, [0, 'OptGeneral'], optionsGroupedBySupplierId);
459
+ const supplierData = {
460
+ supplierId: R.path(['SupplierId'], OptGeneral),
461
+ supplierName: R.path(['SupplierName'], OptGeneral),
462
+ supplierAddress: `${R.pathOr('', ['Address1'], OptGeneral)}, ${R.pathOr('', ['Address2'], OptGeneral)}, ${R.pathOr('', ['Address3'], OptGeneral)}, ${R.pathOr('', ['Address4'], OptGeneral)}, ${R.pathOr('', ['Address5'], OptGeneral)}`,
463
+ serviceTypes: R.uniq(optionsGroupedBySupplierId.map(R.path(['OptGeneral', 'ButtonName']))),
464
+ };
465
+ return translateTPOption({
466
+ supplierData,
467
+ optionsGroupedBySupplierId,
468
+ typeDefs: productTypeDefs,
469
+ query: productQuery,
470
+ });
471
+ }),
472
+ R.values,
473
+ R.groupBy(R.path(['OptGeneral', 'SupplierId'])),
474
+ root => {
475
+ if (!searchInput) return root;
476
+ const getFullSearchStr = o => {
477
+ const fullPptionName = `${R.path(['OptGeneral', 'Description'], o) || ''}-${R.path(['OptGeneral', 'Comment'], o) || ''}`;
478
+ return `${R.path(['OptGeneral', 'SupplierName'], o) || ''} ${fullPptionName} ${R.path(['Opt'], o)} ${R.path(['OptGeneral', 'SupplierId'], o) || ''}`;
479
+ };
480
+ const inputValueLower = searchInput.trim().toLowerCase();
481
+ const parts = inputValueLower.split(' ').filter(Boolean); // Filter out any empty strings just in case
482
+ return root.filter(option => {
483
+ const fullSearchStr = getFullSearchStr(option).toLowerCase();
484
+ return parts.every(part => fullSearchStr.includes(part));
485
+ });
486
+ },
487
+ root => {
488
+ const options = R.pathOr([], ['OptionInfoReply', 'Option'], root);
489
+ // due to the new parser, single option will be returned as an object
490
+ // instead of an array
491
+ if (Array.isArray(options)) return options;
492
+ return [options];
493
+ },
494
+ ), replyObj);
495
+ if (!(products && products.length)) {
496
+ throw new Error('No products found');
489
497
  }
490
498
  return {
491
499
  products,
@@ -673,8 +681,7 @@ class Plugin {
673
681
  ...(puInfo.time && puInfo.time.replace(/\D/g, '') ? {
674
682
  puTime: puInfo.time.replace(/\D/g, ''),
675
683
  } : {}),
676
- puRemark: this.escapeInvalidXmlChars(`${puInfo.time ? `Time: ${puInfo.time || 'NA'},` : ''}
677
- ${puInfo.location ? `Location: ${puInfo.location || 'NA'},` : ''}
684
+ puRemark: this.escapeInvalidXmlChars(`${puInfo.location ? `Location: ${puInfo.location || 'NA'},` : ''}
678
685
  ${puInfo.flightDetails ? `Flight: ${puInfo.flightDetails || 'NA'},` : ''}
679
686
  `),
680
687
  } : {}),
@@ -683,8 +690,7 @@ class Plugin {
683
690
  ...(doInfo.time && doInfo.time.replace(/\D/g, '') ? {
684
691
  doTime: doInfo.time.replace(/\D/g, ''),
685
692
  } : {}),
686
- doRemark: this.escapeInvalidXmlChars(`${doInfo.time ? `Time: ${doInfo.time || 'NA'},` : ''}
687
- ${doInfo.location ? `Location: ${doInfo.location || 'NA'},` : ''}
693
+ doRemark: this.escapeInvalidXmlChars(`${doInfo.location ? `Location: ${doInfo.location || 'NA'},` : ''}
688
694
  ${doInfo.flightDetails ? `Flight: ${doInfo.flightDetails || 'NA'},` : ''}
689
695
  `),
690
696
  } : {}),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ti2-tourplan",
3
- "version": "1.0.41",
3
+ "version": "1.0.42",
4
4
  "description": "Tourplan's TI2 Plugin",
5
5
  "main": "index.js",
6
6
  "scripts": {