tripstorekrabi-shared 1.13.67 → 1.13.68

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/booking.js +169 -132
  2. package/package.json +2 -2
package/booking.js CHANGED
@@ -1,7 +1,7 @@
1
- import dayjs from "dayjs";
1
+ import dayjs from 'dayjs';
2
2
  import advancedFormat from 'dayjs/plugin/advancedFormat.js';
3
- import utc from "dayjs/plugin/utc.js";
4
- import timezone from "dayjs/plugin/timezone.js";
3
+ import utc from 'dayjs/plugin/utc.js';
4
+ import timezone from 'dayjs/plugin/timezone.js';
5
5
  import { PAY_ON_TOUR, calculateTotalOperatorPrice } from './price.js';
6
6
 
7
7
  dayjs.extend(advancedFormat);
@@ -10,131 +10,155 @@ dayjs.extend(timezone);
10
10
 
11
11
  const PHONE_REGEXP = /[^\d+]/g;
12
12
 
13
- export function addBookingFromInvoice(firestore, admin, invoice, paymentData, comment = "") {
14
- let bookingNumberDoc = firestore.collection("meta").doc("BOOKING_NUMBER");
15
-
16
- return firestore
17
- .runTransaction((transaction) => {
18
- return bookingNumberDoc.get().then(async (snapshot) => {
19
- let nextBookingNumber = (snapshot.get("last") ?? 0) + 1;
20
- let processed = 0;
21
- comment = [comment, invoice.comment].filter(item => item).join(", ") ?? "";
22
-
23
- for (let i = 0; i < invoice.items.length; i++) {
24
- let item = invoice.items[i];
25
-
26
- // process only product items
27
- let hasProduct = item.productId?.length > 0;
28
- let productSnapshot = null;
29
- let productDescription;
30
- if (hasProduct) {
31
- productSnapshot = await firestore.collection("products").doc(item.productId).get();
32
- productDescription = productSnapshot.get("shortName");
33
- } else {
34
- productDescription = item.description;
35
- }
13
+ export function addBookingFromInvoice(
14
+ firestore,
15
+ admin,
16
+ invoice,
17
+ paymentData,
18
+ comment = ''
19
+ ) {
20
+ let bookingNumberDoc = firestore.collection('meta').doc('BOOKING_NUMBER');
21
+
22
+ return firestore.runTransaction((transaction) => {
23
+ return bookingNumberDoc.get().then(async (snapshot) => {
24
+ let nextBookingNumber = (snapshot.get('last') ?? 0) + 1;
25
+ let processed = 0;
26
+ comment =
27
+ [comment, invoice.comment].filter((item) => item).join(', ') ?? '';
28
+
29
+ for (let i = 0; i < invoice.items.length; i++) {
30
+ let item = invoice.items[i];
31
+
32
+ // process only product items
33
+ let hasProduct = item.productId?.length > 0;
34
+ let productSnapshot = null;
35
+ let productDescription;
36
+ if (hasProduct) {
37
+ productSnapshot = await firestore
38
+ .collection('products')
39
+ .doc(item.productId)
40
+ .get();
41
+ productDescription = productSnapshot.get('shortName');
42
+ } else {
43
+ productDescription = item.description;
44
+ }
36
45
 
37
- let data = {
38
- referenceNumber: "TSK" + (nextBookingNumber + processed),
39
- hint: "",
40
- specialRequirements: item.dietary?.toUpperCase() ?? "",
41
- productDescription,
42
- productRef: hasProduct ? firestore.collection("products").doc(item.productId) : null,
43
- operator: productSnapshot?.get("operator.default.name") ?? "",
44
- departureDate: admin.firestore.Timestamp.fromDate(dayjs(item.departureDate).toDate()),
45
- schedule: item.schedule ?? "",
46
- pickupTime: "?",
47
- adults: item.adults ?? 0,
48
- children: item.children ?? 0,
49
- infants: item.infants ?? 0,
50
- leadTraveller: invoice.name,
51
- email: invoice.email ?? "",
52
- phoneNumber: invoice.phoneNumber ?? "",
53
- cc: "",
54
- customerBookingStatus: "Pending",
55
- operatorBookingStatus: "Pending",
56
- sentToOperator: false,
57
- startingPointDescription: "",
58
- pickupHotel: item.pickupHotel ?? null,
59
- roomNumber: item.roomNumber ?? "",
60
- flight: item.flight ?? null,
61
- train: item.train ?? null,
62
- comment,
63
- customerPaymentStatus: "Paid",
64
- operatorPaymentStatus: "Pending",
65
- extraPayments: {},
66
- addOns: item.addOns ?? null,
67
- labels: ["NEW"],
68
- paypalInvoiceId: "",
69
- paypalTransactionId: "",
70
- omiseChargeId: "", invoiceNumber: "",
71
- date: admin.firestore.FieldValue.serverTimestamp(),
72
- createdBy: "Trip Store Krabi Next",
73
- lastModified: dayjs().toDate(),
74
- lastModifiedBy: "Trip Store Krabi Next"
75
- };
76
-
77
- if (item.startingPointId) {
78
- data.startingPointId = item.startingPointId;
79
- }
46
+ let data = {
47
+ referenceNumber: 'TSK' + (nextBookingNumber + processed),
48
+ hint: '',
49
+ specialRequirements: item.dietary?.toUpperCase() ?? '',
50
+ productDescription,
51
+ productRef: hasProduct
52
+ ? firestore.collection('products').doc(item.productId)
53
+ : null,
54
+ operator: productSnapshot?.get('operator.default.name') ?? '',
55
+ departureDate: admin.firestore.Timestamp.fromDate(
56
+ dayjs(item.departureDate).toDate()
57
+ ),
58
+ schedule: item.schedule ?? '',
59
+ pickupTime: '?',
60
+ adults: item.adults ?? 0,
61
+ children: item.children ?? 0,
62
+ infants: item.infants ?? 0,
63
+ leadTraveller: invoice.name,
64
+ email: invoice.email ?? '',
65
+ phoneNumber: invoice.phoneNumber ?? '',
66
+ cc: '',
67
+ customerBookingStatus: 'Pending',
68
+ operatorBookingStatus: 'Pending',
69
+ sentToOperator: false,
70
+ startingPointDescription: '',
71
+ pickupHotel: item.pickupHotel ?? null,
72
+ roomNumber: item.roomNumber ?? '',
73
+ flight: item.flight ?? null,
74
+ train: item.train ?? null,
75
+ comment,
76
+ customerPaymentStatus: 'Paid',
77
+ operatorPaymentStatus: 'Pending',
78
+ extraPayments: {},
79
+ addOns: item.addOns ?? null,
80
+ labels: ['NEW'],
81
+ paypalInvoiceId: '',
82
+ paypalTransactionId: '',
83
+ omiseChargeId: '',
84
+ invoiceNumber: '',
85
+ date: admin.firestore.FieldValue.serverTimestamp(),
86
+ createdBy: 'Trip Store Krabi Next',
87
+ lastModified: dayjs().toDate(),
88
+ lastModifiedBy: 'Trip Store Krabi Next',
89
+ };
90
+
91
+ if (item.startingPointId) {
92
+ data.startingPointId = item.startingPointId;
93
+ }
80
94
 
81
- if (item.dropoffHotel && item.dropoffHotel.length > 0) {
82
- data.dropoffHotel = item.dropoffHotel;
83
- }
95
+ if (item.dropoffHotel && item.dropoffHotel.length > 0) {
96
+ data.dropoffHotel = item.dropoffHotel;
97
+ }
84
98
 
85
- if (i > 0) {
86
- data.partnerNetPrice = 0;
87
- }
99
+ if (i > 0) {
100
+ data.partnerNetPrice = 0;
101
+ }
88
102
 
89
- if (item.nationalParkFee) {
90
- data.nationalParkFee = item.nationalParkFee;
91
- }
103
+ if (item.nationalParkFee) {
104
+ data.nationalParkFee = item.nationalParkFee;
105
+ }
92
106
 
93
- if (item.tourGuideLanguage) {
94
- data.tourGuideLanguage = item.tourGuideLanguage;
95
- }
107
+ if (item.tourGuideLanguage) {
108
+ data.tourGuideLanguage = item.tourGuideLanguage;
109
+ }
96
110
 
97
- let endPointId = item.endPointId;
98
- if (!endPointId) {
99
- let endPoints = productSnapshot?.get("endPoints");
100
- if (endPoints && endPoints.length === 1) {
101
- endPointId = endPoints[0].id;
102
- }
103
- }
104
- if (endPointId) {
105
- data.endPointId = endPointId;
111
+ let endPointId = item.endPointId;
112
+ if (!endPointId) {
113
+ let endPoints = productSnapshot?.get('endPoints');
114
+ if (endPoints && endPoints.length === 1) {
115
+ endPointId = endPoints[0].id;
106
116
  }
117
+ }
118
+ if (endPointId) {
119
+ data.endPointId = endPointId;
120
+ }
107
121
 
108
- if (productSnapshot) {
109
- data.operatorNetPrice = calculateTotalOperatorPrice(data, productSnapshot.data());
110
- } else {
111
- data.operatorNetPrice = 0;
112
- }
122
+ if (productSnapshot) {
123
+ data.operatorNetPrice = calculateTotalOperatorPrice(
124
+ data,
125
+ productSnapshot.data()
126
+ );
127
+ } else {
128
+ data.operatorNetPrice = 0;
129
+ }
113
130
 
114
- data = { ...data, ...paymentData };
131
+ data = { ...data, ...paymentData };
115
132
 
116
- let doc = firestore.collection("bookings").doc();
117
- transaction.set(doc, data);
118
- processed++;
119
- }
133
+ let doc = firestore.collection('bookings').doc();
134
+ transaction.set(doc, data);
135
+ processed++;
136
+ }
120
137
 
121
- transaction.set(bookingNumberDoc,
122
- {
123
- last: admin.firestore.FieldValue.increment(processed),
124
- },
125
- { merge: true }
126
- );
127
- });
138
+ transaction.set(
139
+ bookingNumberDoc,
140
+ {
141
+ last: admin.firestore.FieldValue.increment(processed),
142
+ },
143
+ { merge: true }
144
+ );
128
145
  });
146
+ });
129
147
  }
130
148
 
131
149
  export function getOperatorSignature(agent, operatorName, contact) {
132
150
  let signature =
133
- '<br><br>Warm regards,<br><br>' + (agent ? agent + ' - ' : "") + operatorName;
134
- signature +=
135
- `<br>WhatsApp chat: <a href='https://wa.me/${contact.respondNumber.replace(/\D/g, '')}'>${contact.respondNumber}</a>`;
136
- signature +=
137
- `<br>WhatsApp call: <a href='https://wa.me/${contact.whatsappNumber.replace(/\D/g, '')}'>${contact.whatsappNumber}</a>`;
151
+ '<br><br>Warm regards,<br><br>' +
152
+ (agent ? agent + ' - ' : '') +
153
+ operatorName;
154
+ signature += `<br>WhatsApp chat: <a href='https://wa.me/${contact.respondNumber.replace(
155
+ /\D/g,
156
+ ''
157
+ )}'>${contact.respondNumber}</a>`;
158
+ signature += `<br>WhatsApp call: <a href='https://wa.me/${contact.whatsappNumber.replace(
159
+ /\D/g,
160
+ ''
161
+ )}'>${contact.whatsappNumber}</a>`;
138
162
  signature +=
139
163
  "<br>Telegram chat: <a href='https://t.me/tripstorekrabi_bot'>@tripstorekrabi_bot</a>";
140
164
  return signature;
@@ -144,7 +168,7 @@ export function buildIndex(id, booking) {
144
168
  let referenceNumbers = [booking.referenceNumber];
145
169
  if (booking.expediaVoucherNumbers) {
146
170
  booking.expediaVoucherNumbers.forEach((voucherNumber) => {
147
- referenceNumbers.push(voucherNumber + "");
171
+ referenceNumbers.push(voucherNumber + '');
148
172
  });
149
173
  }
150
174
 
@@ -157,7 +181,7 @@ export function buildIndex(id, booking) {
157
181
 
158
182
  let emails = [];
159
183
  let email = booking.email;
160
- if (email && email !== "info@tripstorekrabi.com") {
184
+ if (email && email !== 'info@tripstorekrabi.com') {
161
185
  emails.push(email);
162
186
  }
163
187
 
@@ -165,7 +189,7 @@ export function buildIndex(id, booking) {
165
189
  emails.push(booking.cc);
166
190
  }
167
191
 
168
- let pickupHotel = booking.pickupHotel ?? "";
192
+ let pickupHotel = booking.pickupHotel ?? '';
169
193
 
170
194
  let phoneNumbers = [];
171
195
  let phoneNumber = booking.phoneNumber;
@@ -178,18 +202,25 @@ export function buildIndex(id, booking) {
178
202
  }
179
203
  phoneNumbers = [...new Set(phoneNumbers)];
180
204
 
181
- return { id, referenceNumbers, travellers, emails, pickupHotel, phoneNumbers };
205
+ return {
206
+ id,
207
+ referenceNumbers,
208
+ travellers,
209
+ emails,
210
+ pickupHotel,
211
+ phoneNumbers,
212
+ };
182
213
  }
183
214
 
184
215
  function addPhoneNumbers(phoneNumbers, phoneNumber) {
185
- phoneNumber = (phoneNumber + "").trim();
186
- phoneNumber = phoneNumber.replace(PHONE_REGEXP, "");
187
- if (phoneNumber.startsWith("+")) {
216
+ phoneNumber = (phoneNumber + '').trim();
217
+ phoneNumber = phoneNumber.replace(PHONE_REGEXP, '');
218
+ if (phoneNumber.startsWith('+')) {
188
219
  phoneNumbers.push(phoneNumber);
189
220
  phoneNumbers.push(phoneNumber.substring(1));
190
221
  } else {
191
222
  phoneNumbers.push(phoneNumber);
192
- phoneNumbers.push("+" + phoneNumber);
223
+ phoneNumbers.push('+' + phoneNumber);
193
224
  }
194
225
  }
195
226
 
@@ -203,13 +234,11 @@ export function getStartingPointMessage(booking, product) {
203
234
  text += ' at ' + booking.pickupTime;
204
235
  }
205
236
 
206
- let now = dayjs().tz("Asia/Bangkok");
207
- let dayjsDate = dayjs.tz(booking.departureDate.toDate(), "Asia/Bangkok");
237
+ let now = dayjs().tz('Asia/Bangkok');
238
+ let dayjsDate = dayjs.tz(booking.departureDate.toDate(), 'Asia/Bangkok');
208
239
  let date = dayjsDate.format('Do MMM');
209
240
 
210
- if (
211
- now.add(1, 'day').isSame(dayjsDate, 'day')
212
- ) {
241
+ if (now.add(1, 'day').isSame(dayjsDate, 'day')) {
213
242
  text += ' tomorrow the ' + date;
214
243
  } else if (now.isSame(dayjsDate, 'day')) {
215
244
  text += ' today the ' + date;
@@ -219,10 +248,17 @@ export function getStartingPointMessage(booking, product) {
219
248
 
220
249
  text += '. Please watch out for the staff of ' + booking.operator + '.';
221
250
 
251
+ if (product?.whatToBring?.length > 0) {
252
+ text += '\n\nWHAT TO BRING: ' + product.whatToBring;
253
+ }
254
+
222
255
  if (booking.specialRequirements) {
223
256
  text +=
224
- '\n\nSPECIAL REQUIREMENTS: ' +
225
- booking.specialRequirements.toUpperCase();
257
+ '\n\nSPECIAL REQUIREMENTS: ' + booking.specialRequirements.toUpperCase();
258
+ }
259
+
260
+ if (product?.customerInformation?.length > 0) {
261
+ text += '\n\nIMPORTANT INFORMATION: ' + product.customerInformation;
226
262
  }
227
263
 
228
264
  let payOnTour = [];
@@ -233,8 +269,7 @@ export function getStartingPointMessage(booking, product) {
233
269
  item += ' to ' + product?.nationalPark.title;
234
270
  }
235
271
 
236
- if (product?.nationalPark?.pricing
237
- ) {
272
+ if (product?.nationalPark?.pricing) {
238
273
  item +=
239
274
  ' of ' +
240
275
  product.nationalPark.pricing.adult +
@@ -247,12 +282,14 @@ export function getStartingPointMessage(booking, product) {
247
282
  payOnTour.push(` • ${item}`);
248
283
  }
249
284
 
250
- let extraPayments = Object.values(booking.extraPayments).filter((item) => !item.disabled && item.paymentMethod === PAY_ON_TOUR).map((item) => ` • ${item.description}: ${item.price} THB`);
285
+ let extraPayments = Object.values(booking.extraPayments)
286
+ .filter((item) => !item.disabled && item.paymentMethod === PAY_ON_TOUR)
287
+ .map((item) => ` • ${item.description}: ${item.price} THB`);
251
288
  payOnTour = [...payOnTour, ...extraPayments];
252
289
  if (payOnTour.length > 0) {
253
- text += '\n\nTO BE PAID ON TOUR:\n' + payOnTour.join("\n");
290
+ text += '\n\nTO BE PAID ON TOUR:\n' + payOnTour.join('\n');
254
291
  text += '\n\nPlease bring the total amount in cash to the trip.';
255
292
  }
256
293
 
257
294
  return text;
258
- }
295
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tripstorekrabi-shared",
3
- "version": "1.13.67",
3
+ "version": "1.13.68",
4
4
  "description": "Shared library for Trip Store Krabi",
5
5
  "author": "Stefan Sommer <tonprince@gmail.com>",
6
6
  "repository": {
@@ -15,7 +15,7 @@
15
15
  "./product": "./product.js"
16
16
  },
17
17
  "dependencies": {
18
- "dayjs": "^1.11.9"
18
+ "dayjs": "^1.11.10"
19
19
  },
20
20
  "scripts": {
21
21
  "deploy": "npm publish"