@driveflux/api-functions 1.0.118 → 1.0.119
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/dist/auth/confirm.js +24 -24
- package/dist/auth/consent.js +22 -27
- package/dist/auth/emails.js +12 -13
- package/dist/auth/formatter.js +5 -5
- package/dist/auth/otp.js +66 -50
- package/dist/auth/register.js +48 -35
- package/dist/auth/tokens.js +58 -55
- package/dist/auth/verifications.js +53 -52
- package/dist/constants.js +0 -1
- package/dist/create-logger.js +1 -2
- package/dist/mailjet/calls/manage-contacts-in-list.js +5 -6
- package/dist/mailjet/calls/manage-subscription-status.js +4 -5
- package/dist/mailjet/calls/request-service.js +7 -6
- package/dist/mailjet/refresh-email-preferences.js +11 -12
- package/dist/mailjet/set-contact.js +11 -12
- package/dist/mailjet/types.js +1 -2
- package/dist/mailjet/utils/convert-to-array.js +8 -6
- package/dist/mailjet/utils/extract-email-preferences.js +14 -15
- package/dist/mailjet/utils/lists.js +7 -8
- package/dist/mailjet/utils/update-email-references.js +16 -15
- package/dist/notion/client.js +22 -19
- package/dist/notion/helpful.js +6 -9
- package/dist/notion/schemas/block.js +42 -48
- package/dist/notion/schemas/common.js +9 -14
- package/dist/notion/schemas/database.js +62 -60
- package/dist/notion/schemas/emoji.js +1 -2
- package/dist/notion/schemas/file.js +9 -9
- package/dist/notion/schemas/kb.js +5 -6
- package/dist/notion/schemas/page.js +72 -61
- package/dist/notion/schemas/parent.js +4 -5
- package/dist/notion/schemas/user.js +18 -19
- package/dist/reservation/agree.js +2 -3
- package/dist/reservation/checks.js +3 -4
- package/dist/reservation/display-vehicle.js +73 -83
- package/dist/reservation/ensure-user-billing-address.js +9 -11
- package/dist/reservation/fetch-or-create.js +49 -56
- package/dist/reservation/invoice.js +77 -88
- package/dist/reservation/payer.js +5 -6
- package/dist/reservation/payment-intent-sync.js +4 -6
- package/dist/reservation/reserve.js +3 -4
- package/dist/reservation/types.js +1 -2
- package/dist/reservation/vehicle.js +13 -16
- package/dist/slack.js +24 -29
- package/dist/validation.js +77 -79
- package/dist/vehicle/vehicle-pricing/constants.js +22 -19
- package/dist/vehicle/vehicle-pricing/index.js +28 -42
- package/dist/vehicle/vehicle-pricing/types.js +1 -2
- package/package.json +9 -9
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { config } from '@driveflux/config/backend';
|
|
2
2
|
import { loadCoupon, PROBLEM_APPLICABLE_NOT_FOUND } from '@driveflux/coupon';
|
|
3
|
-
import { prisma
|
|
3
|
+
import { prisma } from '@driveflux/db';
|
|
4
4
|
import { generateId } from '@driveflux/db/id';
|
|
5
5
|
import { EMPTY_BILLING_ADDRESS } from '@driveflux/db/models/other';
|
|
6
|
-
import { INVOICE_LINE_CYCLE, INVOICE_LINE_DEPOSIT, INVOICE_LINE_OTHER, INVOICE_LINE_RESERVATION_FEE, PURPOSE_FULL_BOOKING, PURPOSE_RESERVATION
|
|
6
|
+
import { INVOICE_LINE_CYCLE, INVOICE_LINE_DEPOSIT, INVOICE_LINE_OTHER, INVOICE_LINE_RESERVATION_FEE, PURPOSE_FULL_BOOKING, PURPOSE_RESERVATION } from '@driveflux/db/models/subscription';
|
|
7
7
|
import { userName } from '@driveflux/db/models/user';
|
|
8
8
|
import { vehicleName } from '@driveflux/db/models/vehicle';
|
|
9
9
|
import { biller, coupons } from '@driveflux/engine';
|
|
@@ -16,16 +16,15 @@ import { isAfter } from 'date-fns/isAfter';
|
|
|
16
16
|
import { subMinutes } from 'date-fns/subMinutes';
|
|
17
17
|
import { createScopedLogger } from '../create-logger.js';
|
|
18
18
|
const log = createScopedLogger('reservation:invoice');
|
|
19
|
-
export const updateReservationInvoiceIfNeeded = async (oldReservationInvoice, newParams)
|
|
19
|
+
export const updateReservationInvoiceIfNeeded = async (oldReservationInvoice, newParams)=>{
|
|
20
20
|
const couponIsDifferent = oldReservationInvoice.couponCode !== newParams.couponCode;
|
|
21
|
-
if (!couponIsDifferent &&
|
|
22
|
-
oldReservationInvoice.stripePaymentIntentId === newParams.paymentIntentId) {
|
|
21
|
+
if (!couponIsDifferent && oldReservationInvoice.stripePaymentIntentId === newParams.paymentIntentId) {
|
|
23
22
|
return new Ok(oldReservationInvoice);
|
|
24
23
|
}
|
|
25
24
|
// If the coupon or payment intent are differnt we should update the invoice
|
|
26
25
|
let update = {
|
|
27
26
|
stripePaymentIntentId: newParams.paymentIntentId,
|
|
28
|
-
couponCode: newParams.couponCode
|
|
27
|
+
couponCode: newParams.couponCode
|
|
29
28
|
};
|
|
30
29
|
// If the coupon is different, we need to apply the coupon to the invoice
|
|
31
30
|
if (couponIsDifferent) {
|
|
@@ -33,63 +32,56 @@ export const updateReservationInvoiceIfNeeded = async (oldReservationInvoice, ne
|
|
|
33
32
|
const result = await coupons.applyCouponToUnsavedInvoice(newParams.couponCode, oldReservationInvoice);
|
|
34
33
|
if (result.ok) {
|
|
35
34
|
const { discounts, ...rest } = result.val;
|
|
36
|
-
const toDisconnect = discounts
|
|
37
|
-
|
|
38
|
-
:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
: undefined;
|
|
35
|
+
const toDisconnect = discounts ? oldReservationInvoice.discountIds?.filter((id)=>!discounts.connect?.some((d)=>d.id === id)) : undefined;
|
|
36
|
+
const disconnectClauses = toDisconnect?.length ? {
|
|
37
|
+
disconnect: toDisconnect.map((id)=>({
|
|
38
|
+
id
|
|
39
|
+
}))
|
|
40
|
+
} : undefined;
|
|
44
41
|
update = {
|
|
45
42
|
...update,
|
|
46
43
|
...rest,
|
|
47
|
-
...
|
|
48
|
-
|
|
49
|
-
discounts
|
|
50
|
-
|
|
51
|
-
...(disconnectClauses || {}),
|
|
52
|
-
},
|
|
44
|
+
...discounts || disconnectClauses ? {
|
|
45
|
+
discounts: {
|
|
46
|
+
...discounts || {},
|
|
47
|
+
...disconnectClauses || {}
|
|
53
48
|
}
|
|
54
|
-
|
|
49
|
+
} : {},
|
|
55
50
|
metadata: {
|
|
56
51
|
...update.metadata,
|
|
57
|
-
couponCode: newParams.couponCode
|
|
52
|
+
couponCode: newParams.couponCode
|
|
58
53
|
},
|
|
59
54
|
providerMetadata: {
|
|
60
55
|
...update.providerMetadata,
|
|
61
|
-
couponCode: newParams.couponCode
|
|
62
|
-
}
|
|
56
|
+
couponCode: newParams.couponCode
|
|
57
|
+
}
|
|
63
58
|
};
|
|
64
59
|
}
|
|
65
60
|
if (result.err && result.val.code !== PROBLEM_APPLICABLE_NOT_FOUND) {
|
|
66
61
|
return result;
|
|
67
62
|
}
|
|
68
|
-
}
|
|
69
|
-
else if (oldReservationInvoice.discountIds.length) {
|
|
63
|
+
} else if (oldReservationInvoice.discountIds.length) {
|
|
70
64
|
// No discounts, so we disconnect all of them
|
|
71
65
|
update = {
|
|
72
66
|
discounts: {
|
|
73
|
-
disconnect: oldReservationInvoice.discountIds.map((id)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
67
|
+
disconnect: oldReservationInvoice.discountIds.map((id)=>({
|
|
68
|
+
id
|
|
69
|
+
}))
|
|
70
|
+
}
|
|
77
71
|
};
|
|
78
72
|
}
|
|
79
73
|
}
|
|
80
74
|
let updated = await wrapInResult(biller.updateInvoice(oldReservationInvoice.id, update));
|
|
81
75
|
// If the invoice was locked due to pending status and we're more than 1 minute old, we unlock it
|
|
82
76
|
if (updated.err && updated.val.code === 'invoice_pending') {
|
|
83
|
-
if ((oldReservationInvoice.lockedAt
|
|
84
|
-
isAfter(oldReservationInvoice.lockedAt, subMinutes(new Date(), 1))) ||
|
|
85
|
-
!oldReservationInvoice.lockedAt) {
|
|
77
|
+
if (oldReservationInvoice.lockedAt && isAfter(oldReservationInvoice.lockedAt, subMinutes(new Date(), 1)) || !oldReservationInvoice.lockedAt) {
|
|
86
78
|
updated = await wrapInResult(biller.updateInvoice(oldReservationInvoice.id, {
|
|
87
79
|
...update,
|
|
88
80
|
locked: false,
|
|
89
81
|
lockedAt: null,
|
|
90
82
|
lockReason: null,
|
|
91
83
|
unlockAt: null,
|
|
92
|
-
status: 'draft'
|
|
84
|
+
status: 'draft'
|
|
93
85
|
}));
|
|
94
86
|
}
|
|
95
87
|
}
|
|
@@ -98,7 +90,7 @@ export const updateReservationInvoiceIfNeeded = async (oldReservationInvoice, ne
|
|
|
98
90
|
}
|
|
99
91
|
return new Ok(updated.val);
|
|
100
92
|
};
|
|
101
|
-
export const createReservationInvoice = async ({ invoiceId, couponCode, plan, mileagePackage, referralCode, reservationId, paymentIntentId, freeReservation, freeReservationReason, analytics, vehicle, payer, subscribingUser, fullBooking
|
|
93
|
+
export const createReservationInvoice = async ({ invoiceId, couponCode, plan, mileagePackage, referralCode, reservationId, paymentIntentId, freeReservation, freeReservationReason, analytics, vehicle, payer, subscribingUser, fullBooking })=>{
|
|
102
94
|
if (freeReservation && !fullBooking) {
|
|
103
95
|
// It's a free reservation, so we don't need to add a coupon code
|
|
104
96
|
return await wrapInResult(biller.createInvoice(getInvoiceCreateDetails({
|
|
@@ -110,21 +102,17 @@ export const createReservationInvoice = async ({ invoiceId, couponCode, plan, mi
|
|
|
110
102
|
freeReservation,
|
|
111
103
|
freeReservationReason,
|
|
112
104
|
analytics,
|
|
113
|
-
reservationId
|
|
105
|
+
reservationId
|
|
114
106
|
})));
|
|
115
107
|
}
|
|
116
108
|
let finalCouponCode = couponCode;
|
|
117
109
|
// If we don't have a reservation coupon ID, we apply the referral discount if any
|
|
118
|
-
const referral = referralCode &&
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (!finalCouponCode &&
|
|
125
|
-
referral &&
|
|
126
|
-
referral.discountToReceiverCouponId &&
|
|
127
|
-
referral.discountToReceiverCouponApplicationName === 'reservationFee') {
|
|
110
|
+
const referral = referralCode && await prisma.referral.findUnique({
|
|
111
|
+
where: {
|
|
112
|
+
id: referralCode
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
if (!finalCouponCode && referral && referral.discountToReceiverCouponId && referral.discountToReceiverCouponApplicationName === 'reservationFee') {
|
|
128
116
|
const referralCoupon = await loadCoupon(referral.discountToReceiverCouponId);
|
|
129
117
|
if (referralCoupon) {
|
|
130
118
|
finalCouponCode = referralCoupon.code;
|
|
@@ -143,8 +131,8 @@ export const createReservationInvoice = async ({ invoiceId, couponCode, plan, mi
|
|
|
143
131
|
freeReservation,
|
|
144
132
|
freeReservationReason,
|
|
145
133
|
analytics,
|
|
146
|
-
reservationId
|
|
147
|
-
})
|
|
134
|
+
reservationId
|
|
135
|
+
})
|
|
148
136
|
};
|
|
149
137
|
if (fullBooking) {
|
|
150
138
|
invoiceCreateDetails.subscriptionPurpose = PURPOSE_FULL_BOOKING;
|
|
@@ -156,31 +144,32 @@ export const createReservationInvoice = async ({ invoiceId, couponCode, plan, mi
|
|
|
156
144
|
{
|
|
157
145
|
amount: vehiclePrice,
|
|
158
146
|
chargingFor: INVOICE_LINE_CYCLE,
|
|
159
|
-
description: `First payment for ${vehicleName(vehicle)}
|
|
147
|
+
description: `First payment for ${vehicleName(vehicle)}`
|
|
160
148
|
},
|
|
161
149
|
{
|
|
162
150
|
amount: vehiclePrice * config.taxRate,
|
|
163
151
|
chargingFor: INVOICE_LINE_OTHER,
|
|
164
|
-
description: `Processing fee for ${vehicleName(vehicle)}
|
|
152
|
+
description: `Processing fee for ${vehicleName(vehicle)}`
|
|
165
153
|
},
|
|
166
154
|
{
|
|
167
155
|
amount: vehiclePrice,
|
|
168
156
|
description: `Deposit for ${vehicleName(vehicle)}`,
|
|
169
|
-
chargingFor: INVOICE_LINE_DEPOSIT
|
|
170
|
-
}
|
|
157
|
+
chargingFor: INVOICE_LINE_DEPOSIT
|
|
158
|
+
}
|
|
171
159
|
];
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
160
|
+
} else {
|
|
174
161
|
invoiceCreateDetails.lines = [
|
|
175
162
|
{
|
|
176
163
|
amount: reservationAmount,
|
|
177
164
|
description: `Reservation fee for ${vehicleName(vehicle)}`,
|
|
178
|
-
chargingFor: INVOICE_LINE_RESERVATION_FEE
|
|
179
|
-
}
|
|
165
|
+
chargingFor: INVOICE_LINE_RESERVATION_FEE
|
|
166
|
+
}
|
|
180
167
|
];
|
|
181
168
|
}
|
|
182
169
|
if (finalCouponCode) {
|
|
183
|
-
log.debug({
|
|
170
|
+
log.debug({
|
|
171
|
+
finalCouponCode
|
|
172
|
+
}, 'Applying coupon code to invoice');
|
|
184
173
|
const withCoupon = await coupons.applyCouponToUnsavedInvoice(finalCouponCode, invoiceCreateDetails, 'reservationFee', {
|
|
185
174
|
subscriptionPlans: plan,
|
|
186
175
|
subscriptionMileagePackages: mileagePackage,
|
|
@@ -188,24 +177,25 @@ export const createReservationInvoice = async ({ invoiceId, couponCode, plan, mi
|
|
|
188
177
|
vehicleMake: vehicle.make,
|
|
189
178
|
userId: subscribingUser.id,
|
|
190
179
|
businessId: payer.object === 'business' ? payer.id : undefined,
|
|
191
|
-
vehicleType: vehicle.type
|
|
180
|
+
vehicleType: vehicle.type
|
|
192
181
|
});
|
|
193
|
-
if (withCoupon.err &&
|
|
194
|
-
withCoupon.val.code !== PROBLEM_APPLICABLE_NOT_FOUND) {
|
|
182
|
+
if (withCoupon.err && withCoupon.val.code !== PROBLEM_APPLICABLE_NOT_FOUND) {
|
|
195
183
|
return withCoupon;
|
|
196
184
|
}
|
|
197
|
-
log.debug({
|
|
185
|
+
log.debug({
|
|
186
|
+
couponUpdates: withCoupon.val
|
|
187
|
+
}, 'Coupon applied to invoice');
|
|
198
188
|
if (withCoupon.ok) {
|
|
199
189
|
invoiceCreateDetails = {
|
|
200
190
|
...withCoupon.val,
|
|
201
191
|
metadata: {
|
|
202
192
|
...withCoupon.val.metadata,
|
|
203
|
-
couponCode: finalCouponCode
|
|
193
|
+
couponCode: finalCouponCode
|
|
204
194
|
},
|
|
205
195
|
providerMetadata: {
|
|
206
196
|
...withCoupon.val.providerMetadata,
|
|
207
|
-
couponCode: finalCouponCode
|
|
208
|
-
}
|
|
197
|
+
couponCode: finalCouponCode
|
|
198
|
+
}
|
|
209
199
|
};
|
|
210
200
|
}
|
|
211
201
|
}
|
|
@@ -217,9 +207,7 @@ export const createReservationInvoice = async ({ invoiceId, couponCode, plan, mi
|
|
|
217
207
|
if (paymentIntentResult.err) {
|
|
218
208
|
return new Err(makeProblem(PROBLEM_EXTERNAL, 'Payment intent not found'));
|
|
219
209
|
}
|
|
220
|
-
if (paymentIntentResult.val.amount !==
|
|
221
|
-
currency(biller.getCorrectedInvoiceData(invoiceCreateDetails).total)
|
|
222
|
-
.intValue) {
|
|
210
|
+
if (paymentIntentResult.val.amount !== currency(biller.getCorrectedInvoiceData(invoiceCreateDetails).total).intValue) {
|
|
223
211
|
return new Err(makeProblem(PROBLEM_EXTERNAL, 'Payment intent amount does not match invoice amount'));
|
|
224
212
|
}
|
|
225
213
|
}
|
|
@@ -227,15 +215,15 @@ export const createReservationInvoice = async ({ invoiceId, couponCode, plan, mi
|
|
|
227
215
|
...invoiceCreateDetails,
|
|
228
216
|
providerMetadata: {
|
|
229
217
|
...invoiceCreateDetails.providerMetadata,
|
|
230
|
-
invoiceId: invoiceCreateDetails.id
|
|
231
|
-
}
|
|
218
|
+
invoiceId: invoiceCreateDetails.id
|
|
219
|
+
}
|
|
232
220
|
}));
|
|
233
221
|
if (result.err) {
|
|
234
222
|
return result;
|
|
235
223
|
}
|
|
236
224
|
return new Ok(result.val);
|
|
237
225
|
};
|
|
238
|
-
const getInvoiceCreateDetails = ({ invoiceId, payer, date, reservationDiscountId, vehicle, plan, mileagePackage, couponCode, paymentIntentId, freeReservation, freeReservationReason, analytics, reservationId
|
|
226
|
+
const getInvoiceCreateDetails = ({ invoiceId, payer, date, reservationDiscountId, vehicle, plan, mileagePackage, couponCode, paymentIntentId, freeReservation, freeReservationReason, analytics, reservationId })=>{
|
|
239
227
|
return {
|
|
240
228
|
id: invoiceId || generateId('Invoice'),
|
|
241
229
|
taxPercentage: 0,
|
|
@@ -251,15 +239,13 @@ const getInvoiceCreateDetails = ({ invoiceId, payer, date, reservationDiscountId
|
|
|
251
239
|
description: 'Reservation fee for a FLUX subscription',
|
|
252
240
|
footer: `Invoice for a FLUX subscription reservation. Due by ${format(date ?? new Date())}`,
|
|
253
241
|
invoiceUrl: `${config.appUrl}/invoice-preview/${invoiceId}`,
|
|
254
|
-
...
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
},
|
|
260
|
-
},
|
|
242
|
+
...reservationDiscountId ? {
|
|
243
|
+
discounts: {
|
|
244
|
+
connect: {
|
|
245
|
+
id: reservationDiscountId
|
|
246
|
+
}
|
|
261
247
|
}
|
|
262
|
-
|
|
248
|
+
} : {},
|
|
263
249
|
lines: [],
|
|
264
250
|
subscriptionDetails: {
|
|
265
251
|
vehicleId: vehicle.id,
|
|
@@ -268,7 +254,7 @@ const getInvoiceCreateDetails = ({ invoiceId, payer, date, reservationDiscountId
|
|
|
268
254
|
variant: vehicle.variant,
|
|
269
255
|
year: vehicle.year,
|
|
270
256
|
plan: plan,
|
|
271
|
-
mileagePackage: mileagePackage
|
|
257
|
+
mileagePackage: mileagePackage
|
|
272
258
|
},
|
|
273
259
|
// Legacy field:
|
|
274
260
|
stripePaymentIntentId: paymentIntentId,
|
|
@@ -278,14 +264,18 @@ const getInvoiceCreateDetails = ({ invoiceId, payer, date, reservationDiscountId
|
|
|
278
264
|
mileagePackage,
|
|
279
265
|
vehicleId: vehicle.id,
|
|
280
266
|
vehicleName: vehicleName(vehicle),
|
|
281
|
-
...
|
|
282
|
-
|
|
267
|
+
...reservationId ? {
|
|
268
|
+
reservationId
|
|
269
|
+
} : {},
|
|
270
|
+
...couponCode ? {
|
|
271
|
+
couponCode
|
|
272
|
+
} : {}
|
|
283
273
|
},
|
|
284
274
|
autoRetry: {
|
|
285
275
|
enabled: false,
|
|
286
276
|
interval: 0,
|
|
287
277
|
maxAttempts: 0,
|
|
288
|
-
attempts: 0
|
|
278
|
+
attempts: 0
|
|
289
279
|
},
|
|
290
280
|
metadata: {
|
|
291
281
|
purpose: PURPOSE_RESERVATION,
|
|
@@ -294,11 +284,10 @@ const getInvoiceCreateDetails = ({ invoiceId, payer, date, reservationDiscountId
|
|
|
294
284
|
plan,
|
|
295
285
|
mileagePackage,
|
|
296
286
|
couponCode,
|
|
297
|
-
...
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
analytics
|
|
301
|
-
}
|
|
287
|
+
...freeReservation && freeReservationReason ? {
|
|
288
|
+
freeReservationReason
|
|
289
|
+
} : {},
|
|
290
|
+
analytics
|
|
291
|
+
}
|
|
302
292
|
};
|
|
303
293
|
};
|
|
304
|
-
//# sourceMappingURL=invoice.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { prisma } from '@driveflux/db';
|
|
2
|
-
import { makeProblem, PROBLEM_CONDITION_FAILED, PROBLEM_NOT_FOUND
|
|
2
|
+
import { makeProblem, PROBLEM_CONDITION_FAILED, PROBLEM_NOT_FOUND } from '@driveflux/problem';
|
|
3
3
|
import { Err, Ok } from '@driveflux/result';
|
|
4
|
-
export const getPayer = async ({ subscribingUser, asBusiness
|
|
4
|
+
export const getPayer = async ({ subscribingUser, asBusiness })=>{
|
|
5
5
|
let business = null;
|
|
6
6
|
let payer = subscribingUser;
|
|
7
7
|
if (asBusiness) {
|
|
@@ -11,8 +11,8 @@ export const getPayer = async ({ subscribingUser, asBusiness, }) => {
|
|
|
11
11
|
// load business
|
|
12
12
|
business = await prisma.business.findUnique({
|
|
13
13
|
where: {
|
|
14
|
-
id: subscribingUser.businessId
|
|
15
|
-
}
|
|
14
|
+
id: subscribingUser.businessId
|
|
15
|
+
}
|
|
16
16
|
});
|
|
17
17
|
if (!business) {
|
|
18
18
|
return new Err(makeProblem(PROBLEM_NOT_FOUND, `The business ${subscribingUser.businessId} was not found.`));
|
|
@@ -26,7 +26,7 @@ export const getPayer = async ({ subscribingUser, asBusiness, }) => {
|
|
|
26
26
|
}
|
|
27
27
|
return new Ok(payer);
|
|
28
28
|
};
|
|
29
|
-
const checkPayerObjectSanity = (subscriber)
|
|
29
|
+
const checkPayerObjectSanity = (subscriber)=>{
|
|
30
30
|
if (!subscriber.email) {
|
|
31
31
|
return new Err(makeProblem(PROBLEM_CONDITION_FAILED, `Subscriber ${subscriber.id} has no email. Please add a verified email first.`));
|
|
32
32
|
}
|
|
@@ -35,4 +35,3 @@ const checkPayerObjectSanity = (subscriber) => {
|
|
|
35
35
|
}
|
|
36
36
|
return new Ok(true);
|
|
37
37
|
};
|
|
38
|
-
//# sourceMappingURL=payer.js.map
|
|
@@ -3,20 +3,18 @@ import { makeProblem, PROBLEM_EXTERNAL } from '@driveflux/problem';
|
|
|
3
3
|
import { Err, Ok } from '@driveflux/result';
|
|
4
4
|
import { createScopedLogger } from '../create-logger.js';
|
|
5
5
|
const log = createScopedLogger('reservation:payment-intent-sync');
|
|
6
|
-
export const ensurePaymentIntentIdIsSynced = async (invoice, paymentIntentId)
|
|
6
|
+
export const ensurePaymentIntentIdIsSynced = async (invoice, paymentIntentId)=>{
|
|
7
7
|
const stripe = biller.getPaymentProvider('stripe').getStripe();
|
|
8
8
|
try {
|
|
9
9
|
await stripe.paymentIntents.update(paymentIntentId, {
|
|
10
10
|
metadata: {
|
|
11
11
|
...invoice.providerMetadata,
|
|
12
|
-
invoiceId: invoice.id
|
|
13
|
-
}
|
|
12
|
+
invoiceId: invoice.id
|
|
13
|
+
}
|
|
14
14
|
});
|
|
15
15
|
return new Ok(true);
|
|
16
|
-
}
|
|
17
|
-
catch (error) {
|
|
16
|
+
} catch (error) {
|
|
18
17
|
log.error(error, 'Error updating payment intent metadata');
|
|
19
18
|
return new Err(makeProblem(PROBLEM_EXTERNAL, 'Error updating payment intent metadata'));
|
|
20
19
|
}
|
|
21
20
|
};
|
|
22
|
-
//# sourceMappingURL=payment-intent-sync.js.map
|
|
@@ -7,14 +7,14 @@ import { fetchOrCreateReservation } from './fetch-or-create.js';
|
|
|
7
7
|
import { getPayer } from './payer.js';
|
|
8
8
|
import { ensurePaymentIntentIdIsSynced } from './payment-intent-sync.js';
|
|
9
9
|
import { getVehicle } from './vehicle.js';
|
|
10
|
-
const processBody = (body)
|
|
10
|
+
const processBody = (body)=>{
|
|
11
11
|
// Switch mileage package
|
|
12
12
|
if (body.plan === 'plan1' || body.plan === 'planWeekly') {
|
|
13
13
|
body.mileagePackage = 'unlimited';
|
|
14
14
|
}
|
|
15
15
|
return body;
|
|
16
16
|
};
|
|
17
|
-
export const reserveVehicle = async (vehicleId, unprocessed)
|
|
17
|
+
export const reserveVehicle = async (vehicleId, unprocessed)=>{
|
|
18
18
|
const body = processBody(unprocessed);
|
|
19
19
|
// Agree to terms if not done yet
|
|
20
20
|
const agreeToTermsResult = await handleAgreeToTerms(body);
|
|
@@ -49,7 +49,7 @@ export const reserveVehicle = async (vehicleId, unprocessed) => {
|
|
|
49
49
|
const reservationResult = await fetchOrCreateReservation({
|
|
50
50
|
vehicle,
|
|
51
51
|
payer,
|
|
52
|
-
body
|
|
52
|
+
body
|
|
53
53
|
});
|
|
54
54
|
if (reservationResult.err) {
|
|
55
55
|
return reservationResult;
|
|
@@ -65,4 +65,3 @@ export const reserveVehicle = async (vehicleId, unprocessed) => {
|
|
|
65
65
|
}
|
|
66
66
|
return new Ok(reservation);
|
|
67
67
|
};
|
|
68
|
-
//# sourceMappingURL=reserve.js.map
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export {};
|
|
2
|
-
//# sourceMappingURL=types.js.map
|
|
1
|
+
export { };
|
|
@@ -4,21 +4,19 @@ import { makeProblem, PROBLEM_NOT_FOUND } from '@driveflux/problem';
|
|
|
4
4
|
import { Err, Ok } from '@driveflux/result';
|
|
5
5
|
import { checkIfVehicleIsAvailableForReservation } from './checks.js';
|
|
6
6
|
import { createVehicleFromDisplayVehicle } from './display-vehicle.js';
|
|
7
|
-
export const getVehicle = async (id, { selectedColor, plan, requestUser
|
|
8
|
-
const vehicle = id.startsWith('DV_')
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
},
|
|
21
|
-
});
|
|
7
|
+
export const getVehicle = async (id, { selectedColor, plan, requestUser }, requesterAbility)=>{
|
|
8
|
+
const vehicle = id.startsWith('DV_') ? await createVehicleFromDisplayVehicle(id, selectedColor || undefined) : await prisma.vehicle.findUnique({
|
|
9
|
+
where: {
|
|
10
|
+
id
|
|
11
|
+
},
|
|
12
|
+
include: {
|
|
13
|
+
host: {
|
|
14
|
+
select: {
|
|
15
|
+
id: true
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
});
|
|
22
20
|
if (!vehicle) {
|
|
23
21
|
return new Err(makeProblem(PROBLEM_NOT_FOUND, 'Vehicle not found'));
|
|
24
22
|
}
|
|
@@ -29,4 +27,3 @@ export const getVehicle = async (id, { selectedColor, plan, requestUser, }, requ
|
|
|
29
27
|
}
|
|
30
28
|
return new Ok(vehicle);
|
|
31
29
|
};
|
|
32
|
-
//# sourceMappingURL=vehicle.js.map
|
package/dist/slack.js
CHANGED
|
@@ -10,12 +10,11 @@ const slackBlocks = global.__slackBlocks;
|
|
|
10
10
|
/**
|
|
11
11
|
*
|
|
12
12
|
* @deprecated Use slackLater instead and commitSlack to commit
|
|
13
|
-
*/
|
|
14
|
-
export const slack = async (message, channel = config.slack.defaultChannelId) => {
|
|
13
|
+
*/ export const slack = async (message, channel = config.slack.defaultChannelId)=>{
|
|
15
14
|
return await enhancedFetch('https://slack.com/api/chat.postMessage', {
|
|
16
15
|
method: 'POST',
|
|
17
16
|
headers: {
|
|
18
|
-
Authorization: `Bearer ${config.slack.token}
|
|
17
|
+
Authorization: `Bearer ${config.slack.token}`
|
|
19
18
|
},
|
|
20
19
|
body: JSON.stringify({
|
|
21
20
|
channel,
|
|
@@ -24,23 +23,20 @@ export const slack = async (message, channel = config.slack.defaultChannelId) =>
|
|
|
24
23
|
type: 'section',
|
|
25
24
|
text: {
|
|
26
25
|
type: 'mrkdwn',
|
|
27
|
-
text: message
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
]
|
|
31
|
-
})
|
|
26
|
+
text: message
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
})
|
|
32
31
|
});
|
|
33
32
|
};
|
|
34
|
-
export const getSlackBlocks = (channel)
|
|
33
|
+
export const getSlackBlocks = (channel)=>channel ? slackBlocks.get(channel) : slackBlocks;
|
|
35
34
|
/**
|
|
36
35
|
* Naive implementation, however, for now (uncrowded serverless env), this works
|
|
37
36
|
* @param blocks
|
|
38
37
|
* @param channel
|
|
39
|
-
*/
|
|
40
|
-
|
|
41
|
-
const targetChannel = (config.appEnv === 'production'
|
|
42
|
-
? channel
|
|
43
|
-
: config.slack.defaultChannelId) || config.slack.defaultChannelId;
|
|
38
|
+
*/ export function slackLater(blocks, channel) {
|
|
39
|
+
const targetChannel = (config.appEnv === 'production' ? channel : config.slack.defaultChannelId) || config.slack.defaultChannelId;
|
|
44
40
|
if (!targetChannel || !blocks) {
|
|
45
41
|
return;
|
|
46
42
|
}
|
|
@@ -50,15 +46,13 @@ export function slackLater(blocks, channel) {
|
|
|
50
46
|
type: 'section',
|
|
51
47
|
text: {
|
|
52
48
|
type: 'mrkdwn',
|
|
53
|
-
text: blocks
|
|
54
|
-
}
|
|
49
|
+
text: blocks
|
|
50
|
+
}
|
|
55
51
|
});
|
|
56
|
-
}
|
|
57
|
-
else if (!Array.isArray(blocks)) {
|
|
52
|
+
} else if (!Array.isArray(blocks)) {
|
|
58
53
|
messages.add(blocks);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
for (const b of blocks) {
|
|
54
|
+
} else {
|
|
55
|
+
for (const b of blocks){
|
|
62
56
|
messages.add(b);
|
|
63
57
|
}
|
|
64
58
|
}
|
|
@@ -69,22 +63,22 @@ export async function sendSlackMessages(channel, blocks) {
|
|
|
69
63
|
return await enhancedFetch('https://slack.com/api/chat.postMessage', {
|
|
70
64
|
method: 'POST',
|
|
71
65
|
headers: {
|
|
72
|
-
Authorization: `Bearer ${config.slack.token}
|
|
66
|
+
Authorization: `Bearer ${config.slack.token}`
|
|
73
67
|
},
|
|
74
68
|
body: JSON.stringify({
|
|
75
69
|
channel: targetChannel,
|
|
76
|
-
blocks: Array.from(blocks)
|
|
77
|
-
})
|
|
70
|
+
blocks: Array.from(blocks)
|
|
71
|
+
})
|
|
78
72
|
});
|
|
79
73
|
}
|
|
80
|
-
export const commitSlack = ()
|
|
74
|
+
export const commitSlack = ()=>{
|
|
81
75
|
if (!slackBlocks.size) {
|
|
82
76
|
return;
|
|
83
77
|
}
|
|
84
78
|
const channels = slackBlocks.keys();
|
|
85
79
|
let i = 1;
|
|
86
80
|
const baseUrl = config.appEnv === 'development' ? config.tunnelUrl : config.appUrl;
|
|
87
|
-
for (const channel of channels)
|
|
81
|
+
for (const channel of channels){
|
|
88
82
|
const blocks = slackBlocks.get(channel);
|
|
89
83
|
if (!blocks?.size) {
|
|
90
84
|
continue;
|
|
@@ -94,12 +88,13 @@ export const commitSlack = () => {
|
|
|
94
88
|
name: TASK_COMMIT_SLACK_CHANNEL,
|
|
95
89
|
metadata: {
|
|
96
90
|
channel,
|
|
97
|
-
blocks: [
|
|
91
|
+
blocks: [
|
|
92
|
+
...blocks
|
|
93
|
+
]
|
|
98
94
|
},
|
|
99
95
|
taskHandlerUrl: `${baseUrl || config.appUrl}/api/hooks/slack-pipeline`,
|
|
100
|
-
scheduledAt: addSeconds(new Date(), i++)
|
|
96
|
+
scheduledAt: addSeconds(new Date(), i++)
|
|
101
97
|
});
|
|
102
98
|
}
|
|
103
99
|
slackBlocks.clear();
|
|
104
100
|
};
|
|
105
|
-
//# sourceMappingURL=slack.js.map
|