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.
- package/index.js +77 -3
- package/index.test.js +31 -9
- 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:
|
|
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:
|
|
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
|
-
|
|
134
|
+
const { quote } = retVal;
|
|
113
135
|
expect(quote.length).toBeGreaterThan(0);
|
|
114
136
|
expect(quote[0]).toContainObject([{
|
|
115
|
-
|
|
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
|
-
|
|
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
|
});
|