ti2-ventrata 1.0.3 → 1.0.4

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 (3) hide show
  1. package/index.js +77 -3
  2. package/index.test.js +31 -9
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -6,6 +6,8 @@ const moment = require('moment');
6
6
  const jwt = require('jsonwebtoken');
7
7
  const wildcardMatch = require('./utils/wildcardMatch');
8
8
 
9
+ const CONCURRENCY = 3; // is this ok ?
10
+
9
11
  const isNilOrEmpty = R.either(R.isNil, R.isEmpty);
10
12
  const isNilOrEmptyArray = el => {
11
13
  if (!Array.isArray(el)) return true;
@@ -36,7 +38,7 @@ const productMapIn = {
36
38
 
37
39
  const rateMap = {
38
40
  rateId: R.path(['id']),
39
- rateName: R.path(['internalName']),
41
+ rateName: rateName => R.toLower(R.path(['internalName'], rateName)),
40
42
  pricing: R.path(['pricingFrom']),
41
43
  };
42
44
 
@@ -245,7 +247,7 @@ class Plugin {
245
247
  url,
246
248
  headers,
247
249
  });
248
- }, { concurrency: 3 /* is this ok ? */ }).map(({ data }) => data);
250
+ }, { concurrency: CONCURRENCY }).map(({ data }) => data);
249
251
  productsDetail = R.indexBy(R.prop('id'), productsDetail);
250
252
  // console.log({ optionIds });
251
253
  productIds.forEach((productId, productIdIx) => {
@@ -324,7 +326,7 @@ class Plugin {
324
326
  data,
325
327
  headers,
326
328
  });
327
- }, { concurrency: 3 }) // is this ok ?
329
+ }, { concurrency: CONCURRENCY })
328
330
  ).map(({ data }) => data);
329
331
  availability = availability.map(
330
332
  (avails, availsIx) => (avails.map(
@@ -345,6 +347,78 @@ class Plugin {
345
347
  return { availability };
346
348
  }
347
349
 
350
+ async availabilityCalendar({
351
+ token: {
352
+ apiKey = this.apiKey,
353
+ endpoint = this.endpoint,
354
+ octoEnv = this.octoEnv,
355
+ acceptLanguage = this.acceptLanguage,
356
+ },
357
+ token,
358
+ payload: {
359
+ productIds,
360
+ optionIds,
361
+ occupancies,
362
+ startDate,
363
+ // endDate,
364
+ dateFormat,
365
+ },
366
+ }) {
367
+ assert(this.jwtKey, 'JWT secret should be set');
368
+ assert(occupancies.length > 0, 'there should be at least one occupancy');
369
+ assert(
370
+ productIds.length === optionIds.length,
371
+ 'mismatched productIds/options length',
372
+ );
373
+ assert(
374
+ optionIds.length === occupancies.length,
375
+ 'mismatched options/occupancies length',
376
+ );
377
+ assert(productIds.every(Boolean), 'some invalid productId(s)');
378
+ assert(optionIds.every(Boolean), 'some invalid optionId(s)');
379
+ assert(occupancies.every(Boolean), 'some invalid occupacies(s)');
380
+ const localDateStart = moment(startDate, dateFormat).format('YYYY-MM-DD');
381
+ const localDateEnd = moment(startDate, dateFormat).format('YYYY-MM-DD');
382
+ // obtain the rates
383
+ const { quote } = await this.searchQuote({
384
+ token,
385
+ payload: {
386
+ productIds,
387
+ optionIds,
388
+ occupancies,
389
+ },
390
+ });
391
+ const rates = quote.map(q => q.map(({ rateId }) => rateId));
392
+ const headers = getHeaders({
393
+ apiKey,
394
+ endpoint,
395
+ octoEnv,
396
+ acceptLanguage,
397
+ });
398
+ const url = `${endpoint || this.endpoint}/availability/calendar`;
399
+ const availability = (
400
+ await Promise.map(rates, async (rate, rateIx) => {
401
+ const qtys = R.countBy(x => x)(rate);
402
+ const data = {
403
+ productId: productIds[rateIx],
404
+ optionId: optionIds[rateIx],
405
+ localDateStart,
406
+ localDateEnd,
407
+ units: Object.entries(qtys).map(([id, quantity]) => ({
408
+ id, quantity,
409
+ })),
410
+ };
411
+ return axios({
412
+ method: 'post',
413
+ url,
414
+ data,
415
+ headers,
416
+ });
417
+ }, { concurrency: CONCURRENCY })
418
+ ).map(({ data }) => data);
419
+ return { availability };
420
+ }
421
+
348
422
  async createBooking({
349
423
  token: {
350
424
  apiKey = this.apiKey,
package/index.test.js CHANGED
@@ -85,12 +85,35 @@ describe('search tests', () => {
85
85
  token,
86
86
  payload: {
87
87
  productName: '*bus*',
88
- }
88
+ },
89
89
  });
90
90
  expect(Array.isArray(retVal.products)).toBeTruthy();
91
91
  expect(retVal.products.length).toBeGreaterThan(0);
92
92
  busProducts = retVal.products;
93
93
  });
94
+ it('should be able to get an availability calendar', async () => {
95
+ const retVal = await app.availabilityCalendar({
96
+ token,
97
+ payload: {
98
+ startDate: moment().add(6, 'M').format(dateFormat),
99
+ endDate: moment().add(6, 'M').add(2, 'd').format(dateFormat),
100
+ dateFormat,
101
+ productIds: [
102
+ '28ca088b-bc7b-4746-ab06-5971f1ed5a5e',
103
+ '5d981651-e204-4549-bfbe-691043dd2515',
104
+ ],
105
+ optionIds: ['DEFAULT', 'DEFAULT'],
106
+ occupancies: [
107
+ [{ age: 30 }, { age: 40 }],
108
+ [{ age: 30 }, { age: 40 }],
109
+ ],
110
+ },
111
+ });
112
+ expect(retVal).toBeTruthy();
113
+ const { availability } = retVal;
114
+ expect(availability).toHaveLength(2);
115
+ expect(availability[0].length).toBeGreaterThan(0);
116
+ });
94
117
  it('should be able to get quotes', async () => {
95
118
  const retVal = await app.searchQuote({
96
119
  token,
@@ -99,9 +122,8 @@ describe('search tests', () => {
99
122
  endDate: moment().add(6, 'M').add(2, 'd').format(dateFormat),
100
123
  dateFormat,
101
124
  productIds: busProducts.map(({ productId }) => productId),
102
- optionIds: busProducts.map(({ options }) =>
103
- faker.random.arrayElement(options).optionId
104
- ),
125
+ optionIds: busProducts.map(({ options }) =>
126
+ faker.random.arrayElement(options).optionId),
105
127
  occupancies: [
106
128
  [{ age: 30 }, { age: 40 }],
107
129
  [{ age: 30 }, { age: 40 }],
@@ -109,10 +131,10 @@ describe('search tests', () => {
109
131
  },
110
132
  });
111
133
  expect(retVal).toBeTruthy();
112
- ({ quote } = retVal);
134
+ const { quote } = retVal;
113
135
  expect(quote.length).toBeGreaterThan(0);
114
136
  expect(quote[0]).toContainObject([{
115
- rateId: 'adult',
137
+ rateName: 'adult',
116
138
  pricing: expect.toContainObject([{
117
139
  currency: 'USD',
118
140
  }]),
@@ -128,7 +150,7 @@ describe('search tests', () => {
128
150
  dateFormat,
129
151
  productIds: [
130
152
  '28ca088b-bc7b-4746-ab06-5971f1ed5a5e',
131
- '5d981651-e204-4549-bfbe-691043dd2515'
153
+ '5d981651-e204-4549-bfbe-691043dd2515',
132
154
  ],
133
155
  optionIds: ['DEFAULT', 'DEFAULT'],
134
156
  occupancies: [
@@ -138,9 +160,9 @@ describe('search tests', () => {
138
160
  },
139
161
  });
140
162
  expect(retVal).toBeTruthy();
141
- ({ availability } = retVal);
163
+ const { availability } = retVal;
142
164
  expect(availability).toHaveLength(2);
143
- expect(availability[0].length).toBeGreaterThan(0)
165
+ expect(availability[0].length).toBeGreaterThan(0);
144
166
  availabilityKey = R.path([0, 0, 'key'], availability);
145
167
  expect(availabilityKey).toBeTruthy();
146
168
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ti2-ventrata",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Ventrata's TI2 Plugin",
5
5
  "main": "index.js",
6
6
  "scripts": {