@vulog/aima-booking 1.2.21 → 1.2.23

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/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Client } from '@vulog/aima-client';
2
2
  import { PaginableOptions, PaginableResponse } from '@vulog/aima-core';
3
- import { z } from 'zod';
3
+ import z$1, { z } from 'zod';
4
4
  import { UUID } from 'crypto';
5
5
 
6
6
  type PaymentReceipts = {
@@ -18,6 +18,51 @@ type PaymentReceipts = {
18
18
  scope: string;
19
19
  };
20
20
  };
21
+ /** Payment intent or receipt item as returned by trigger BR payment (and similar payment endpoints). */
22
+ type BRPaymentItem = {
23
+ id: string;
24
+ pspName: string;
25
+ pspReference: string;
26
+ pspPublishableKey: string;
27
+ amount: number;
28
+ currency: string;
29
+ date: string;
30
+ captureBefore: string;
31
+ status: string;
32
+ paymentMethodType: string;
33
+ paymentMethodPspReference: string;
34
+ paymentIntentPspReference: string;
35
+ number: number;
36
+ code?: string;
37
+ declineCode?: string;
38
+ pspClientSecret?: string;
39
+ reason?: string;
40
+ note?: string;
41
+ nextAction?: {
42
+ nextActionRedirectUrl: {
43
+ url: string;
44
+ method: string;
45
+ data: Record<string, string>;
46
+ };
47
+ type: string;
48
+ };
49
+ metadatas: Record<string, string>;
50
+ };
51
+ /** Credit entry in a booking request (e.g. trigger BR payment response). */
52
+ type BookingCredit = {
53
+ id: string;
54
+ fleetId: string;
55
+ amount: number;
56
+ availableAmount: number;
57
+ status: string;
58
+ walletId: string;
59
+ date: string;
60
+ };
61
+ /** Preferred payment method entry in request/response. */
62
+ type PreferredPaymentMethod = {
63
+ pspReference: string;
64
+ amount: number;
65
+ };
21
66
  type CustomPrice = {
22
67
  id: string;
23
68
  fleetId: string;
@@ -105,6 +150,13 @@ type SATBookingRequest = BaseBookingRequest & {
105
150
  trip: any | null;
106
151
  warning: string | null;
107
152
  };
153
+ /** Response of the trigger BR payment endpoint (booking request + payment intents/receipts). */
154
+ type TriggerBRPaymentResponse = Omit<SATBookingRequest, 'credits'> & {
155
+ paymentIntents: BRPaymentItem[];
156
+ paymentReceipts: BRPaymentItem[];
157
+ credits: BookingCredit[];
158
+ preferredPaymentMethods?: PreferredPaymentMethod[];
159
+ };
108
160
  type GeoInfo = {
109
161
  name: string;
110
162
  coordinates: {
@@ -147,7 +199,7 @@ type Station = Partial<GeoInfo> & Partial<ServiceInfo> & {
147
199
  [key: string]: any;
148
200
  };
149
201
 
150
- declare const BookingRequestStatusSchema: z.ZodEnum<["ALERT", "UPCOMING", "ONGOING", "COMPLETED", "CANCELLED", "PENDING_APPROVAL"]>;
202
+ declare const BookingRequestStatusSchema: z.ZodEnum<["ALERT", "UPCOMING", "ONGOING", "COMPLETED", "CANCELLED", "PENDING_APPROVAL", "CONFIRMED", "PENDING", "LATE"]>;
151
203
  type BookingRequestStatus = z.infer<typeof BookingRequestStatusSchema>;
152
204
  declare const ServiceTypeSchema: z.ZodEnum<["SUBSCRIPTION", "ROUND_TRIP_BOOKING", "SCHEDULED_BOOKING_STATION"]>;
153
205
  type ServiceType = z.infer<typeof ServiceTypeSchema>;
@@ -202,4 +254,77 @@ declare const deallocateVehicle: (client: Client, bookingRequestId: UUID, vehicl
202
254
 
203
255
  declare const updateScheduleBooking: (client: Client, bookingRequestId: string, updateData: Record<string, unknown>) => Promise<SATBookingRequest>;
204
256
 
205
- export { type BaseBookingRequest, type BookingRequest, type BookingRequestFilters, type BookingRequestStatus, type CustomPrice, type DayOpeningHours, type Days, type GeoInfo, type Include, type IncludeStation, type OpeningHours, type PaymentReceipts, type SATBookingRequest, type SATBookingRequestStatus, type Service, type ServiceInfo, type ServiceType, type Station, type Timetable, allocateVehicle, deallocateVehicle, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getSATBookingRequests, getScheduleBookingRequests, getStationById, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, updateScheduleBooking };
257
+ declare const triggerBRPaymentSchema: z$1.ZodObject<{
258
+ bookingRequestId: z$1.ZodString;
259
+ body: z$1.ZodObject<{
260
+ scope: z$1.ZodEnum<["RENTAL", "DEPOSIT"]>;
261
+ requiresActionReturnURL: z$1.ZodOptional<z$1.ZodString>;
262
+ online: z$1.ZodBoolean;
263
+ amountType: z$1.ZodEnum<["FIXED", "PERCENTAGE"]>;
264
+ amountValue: z$1.ZodNumber;
265
+ preferredPaymentMethods: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
266
+ pspReference: z$1.ZodString;
267
+ amount: z$1.ZodDefault<z$1.ZodNumber>;
268
+ }, "strip", z$1.ZodTypeAny, {
269
+ pspReference: string;
270
+ amount: number;
271
+ }, {
272
+ pspReference: string;
273
+ amount?: number | undefined;
274
+ }>, "many">>;
275
+ profileId: z$1.ZodString;
276
+ }, "strip", z$1.ZodTypeAny, {
277
+ profileId: string;
278
+ scope: "RENTAL" | "DEPOSIT";
279
+ online: boolean;
280
+ amountType: "FIXED" | "PERCENTAGE";
281
+ amountValue: number;
282
+ requiresActionReturnURL?: string | undefined;
283
+ preferredPaymentMethods?: {
284
+ pspReference: string;
285
+ amount: number;
286
+ }[] | undefined;
287
+ }, {
288
+ profileId: string;
289
+ scope: "RENTAL" | "DEPOSIT";
290
+ online: boolean;
291
+ amountType: "FIXED" | "PERCENTAGE";
292
+ amountValue: number;
293
+ requiresActionReturnURL?: string | undefined;
294
+ preferredPaymentMethods?: {
295
+ pspReference: string;
296
+ amount?: number | undefined;
297
+ }[] | undefined;
298
+ }>;
299
+ }, "strip", z$1.ZodTypeAny, {
300
+ body: {
301
+ profileId: string;
302
+ scope: "RENTAL" | "DEPOSIT";
303
+ online: boolean;
304
+ amountType: "FIXED" | "PERCENTAGE";
305
+ amountValue: number;
306
+ requiresActionReturnURL?: string | undefined;
307
+ preferredPaymentMethods?: {
308
+ pspReference: string;
309
+ amount: number;
310
+ }[] | undefined;
311
+ };
312
+ bookingRequestId: string;
313
+ }, {
314
+ body: {
315
+ profileId: string;
316
+ scope: "RENTAL" | "DEPOSIT";
317
+ online: boolean;
318
+ amountType: "FIXED" | "PERCENTAGE";
319
+ amountValue: number;
320
+ requiresActionReturnURL?: string | undefined;
321
+ preferredPaymentMethods?: {
322
+ pspReference: string;
323
+ amount?: number | undefined;
324
+ }[] | undefined;
325
+ };
326
+ bookingRequestId: string;
327
+ }>;
328
+ declare const triggerBRPayment: (client: Client, bookingRequestId: UUID, body: z$1.infer<typeof triggerBRPaymentSchema>["body"]) => Promise<TriggerBRPaymentResponse>;
329
+
330
+ export { type BRPaymentItem, type BaseBookingRequest, type BookingCredit, type BookingRequest, type BookingRequestFilters, type BookingRequestStatus, type CustomPrice, type DayOpeningHours, type Days, type GeoInfo, type Include, type IncludeStation, type OpeningHours, type PaymentReceipts, type PreferredPaymentMethod, type SATBookingRequest, type SATBookingRequestStatus, type Service, type ServiceInfo, type ServiceType, type Station, type Timetable, type TriggerBRPaymentResponse, allocateVehicle, deallocateVehicle, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getSATBookingRequests, getScheduleBookingRequests, getStationById, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, triggerBRPayment, updateScheduleBooking };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Client } from '@vulog/aima-client';
2
2
  import { PaginableOptions, PaginableResponse } from '@vulog/aima-core';
3
- import { z } from 'zod';
3
+ import z$1, { z } from 'zod';
4
4
  import { UUID } from 'crypto';
5
5
 
6
6
  type PaymentReceipts = {
@@ -18,6 +18,51 @@ type PaymentReceipts = {
18
18
  scope: string;
19
19
  };
20
20
  };
21
+ /** Payment intent or receipt item as returned by trigger BR payment (and similar payment endpoints). */
22
+ type BRPaymentItem = {
23
+ id: string;
24
+ pspName: string;
25
+ pspReference: string;
26
+ pspPublishableKey: string;
27
+ amount: number;
28
+ currency: string;
29
+ date: string;
30
+ captureBefore: string;
31
+ status: string;
32
+ paymentMethodType: string;
33
+ paymentMethodPspReference: string;
34
+ paymentIntentPspReference: string;
35
+ number: number;
36
+ code?: string;
37
+ declineCode?: string;
38
+ pspClientSecret?: string;
39
+ reason?: string;
40
+ note?: string;
41
+ nextAction?: {
42
+ nextActionRedirectUrl: {
43
+ url: string;
44
+ method: string;
45
+ data: Record<string, string>;
46
+ };
47
+ type: string;
48
+ };
49
+ metadatas: Record<string, string>;
50
+ };
51
+ /** Credit entry in a booking request (e.g. trigger BR payment response). */
52
+ type BookingCredit = {
53
+ id: string;
54
+ fleetId: string;
55
+ amount: number;
56
+ availableAmount: number;
57
+ status: string;
58
+ walletId: string;
59
+ date: string;
60
+ };
61
+ /** Preferred payment method entry in request/response. */
62
+ type PreferredPaymentMethod = {
63
+ pspReference: string;
64
+ amount: number;
65
+ };
21
66
  type CustomPrice = {
22
67
  id: string;
23
68
  fleetId: string;
@@ -105,6 +150,13 @@ type SATBookingRequest = BaseBookingRequest & {
105
150
  trip: any | null;
106
151
  warning: string | null;
107
152
  };
153
+ /** Response of the trigger BR payment endpoint (booking request + payment intents/receipts). */
154
+ type TriggerBRPaymentResponse = Omit<SATBookingRequest, 'credits'> & {
155
+ paymentIntents: BRPaymentItem[];
156
+ paymentReceipts: BRPaymentItem[];
157
+ credits: BookingCredit[];
158
+ preferredPaymentMethods?: PreferredPaymentMethod[];
159
+ };
108
160
  type GeoInfo = {
109
161
  name: string;
110
162
  coordinates: {
@@ -147,7 +199,7 @@ type Station = Partial<GeoInfo> & Partial<ServiceInfo> & {
147
199
  [key: string]: any;
148
200
  };
149
201
 
150
- declare const BookingRequestStatusSchema: z.ZodEnum<["ALERT", "UPCOMING", "ONGOING", "COMPLETED", "CANCELLED", "PENDING_APPROVAL"]>;
202
+ declare const BookingRequestStatusSchema: z.ZodEnum<["ALERT", "UPCOMING", "ONGOING", "COMPLETED", "CANCELLED", "PENDING_APPROVAL", "CONFIRMED", "PENDING", "LATE"]>;
151
203
  type BookingRequestStatus = z.infer<typeof BookingRequestStatusSchema>;
152
204
  declare const ServiceTypeSchema: z.ZodEnum<["SUBSCRIPTION", "ROUND_TRIP_BOOKING", "SCHEDULED_BOOKING_STATION"]>;
153
205
  type ServiceType = z.infer<typeof ServiceTypeSchema>;
@@ -202,4 +254,77 @@ declare const deallocateVehicle: (client: Client, bookingRequestId: UUID, vehicl
202
254
 
203
255
  declare const updateScheduleBooking: (client: Client, bookingRequestId: string, updateData: Record<string, unknown>) => Promise<SATBookingRequest>;
204
256
 
205
- export { type BaseBookingRequest, type BookingRequest, type BookingRequestFilters, type BookingRequestStatus, type CustomPrice, type DayOpeningHours, type Days, type GeoInfo, type Include, type IncludeStation, type OpeningHours, type PaymentReceipts, type SATBookingRequest, type SATBookingRequestStatus, type Service, type ServiceInfo, type ServiceType, type Station, type Timetable, allocateVehicle, deallocateVehicle, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getSATBookingRequests, getScheduleBookingRequests, getStationById, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, updateScheduleBooking };
257
+ declare const triggerBRPaymentSchema: z$1.ZodObject<{
258
+ bookingRequestId: z$1.ZodString;
259
+ body: z$1.ZodObject<{
260
+ scope: z$1.ZodEnum<["RENTAL", "DEPOSIT"]>;
261
+ requiresActionReturnURL: z$1.ZodOptional<z$1.ZodString>;
262
+ online: z$1.ZodBoolean;
263
+ amountType: z$1.ZodEnum<["FIXED", "PERCENTAGE"]>;
264
+ amountValue: z$1.ZodNumber;
265
+ preferredPaymentMethods: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
266
+ pspReference: z$1.ZodString;
267
+ amount: z$1.ZodDefault<z$1.ZodNumber>;
268
+ }, "strip", z$1.ZodTypeAny, {
269
+ pspReference: string;
270
+ amount: number;
271
+ }, {
272
+ pspReference: string;
273
+ amount?: number | undefined;
274
+ }>, "many">>;
275
+ profileId: z$1.ZodString;
276
+ }, "strip", z$1.ZodTypeAny, {
277
+ profileId: string;
278
+ scope: "RENTAL" | "DEPOSIT";
279
+ online: boolean;
280
+ amountType: "FIXED" | "PERCENTAGE";
281
+ amountValue: number;
282
+ requiresActionReturnURL?: string | undefined;
283
+ preferredPaymentMethods?: {
284
+ pspReference: string;
285
+ amount: number;
286
+ }[] | undefined;
287
+ }, {
288
+ profileId: string;
289
+ scope: "RENTAL" | "DEPOSIT";
290
+ online: boolean;
291
+ amountType: "FIXED" | "PERCENTAGE";
292
+ amountValue: number;
293
+ requiresActionReturnURL?: string | undefined;
294
+ preferredPaymentMethods?: {
295
+ pspReference: string;
296
+ amount?: number | undefined;
297
+ }[] | undefined;
298
+ }>;
299
+ }, "strip", z$1.ZodTypeAny, {
300
+ body: {
301
+ profileId: string;
302
+ scope: "RENTAL" | "DEPOSIT";
303
+ online: boolean;
304
+ amountType: "FIXED" | "PERCENTAGE";
305
+ amountValue: number;
306
+ requiresActionReturnURL?: string | undefined;
307
+ preferredPaymentMethods?: {
308
+ pspReference: string;
309
+ amount: number;
310
+ }[] | undefined;
311
+ };
312
+ bookingRequestId: string;
313
+ }, {
314
+ body: {
315
+ profileId: string;
316
+ scope: "RENTAL" | "DEPOSIT";
317
+ online: boolean;
318
+ amountType: "FIXED" | "PERCENTAGE";
319
+ amountValue: number;
320
+ requiresActionReturnURL?: string | undefined;
321
+ preferredPaymentMethods?: {
322
+ pspReference: string;
323
+ amount?: number | undefined;
324
+ }[] | undefined;
325
+ };
326
+ bookingRequestId: string;
327
+ }>;
328
+ declare const triggerBRPayment: (client: Client, bookingRequestId: UUID, body: z$1.infer<typeof triggerBRPaymentSchema>["body"]) => Promise<TriggerBRPaymentResponse>;
329
+
330
+ export { type BRPaymentItem, type BaseBookingRequest, type BookingCredit, type BookingRequest, type BookingRequestFilters, type BookingRequestStatus, type CustomPrice, type DayOpeningHours, type Days, type GeoInfo, type Include, type IncludeStation, type OpeningHours, type PaymentReceipts, type PreferredPaymentMethod, type SATBookingRequest, type SATBookingRequestStatus, type Service, type ServiceInfo, type ServiceType, type Station, type Timetable, type TriggerBRPaymentResponse, allocateVehicle, deallocateVehicle, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getSATBookingRequests, getScheduleBookingRequests, getStationById, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, triggerBRPayment, updateScheduleBooking };
package/dist/index.js CHANGED
@@ -41,6 +41,7 @@ __export(index_exports, {
41
41
  getStations: () => getStations,
42
42
  getSubscriptionBookingRequestById: () => getSubscriptionBookingRequestById,
43
43
  getSubscriptionBookingRequests: () => getSubscriptionBookingRequests,
44
+ triggerBRPayment: () => triggerBRPayment,
44
45
  updateScheduleBooking: () => updateScheduleBooking
45
46
  });
46
47
  module.exports = __toCommonJS(index_exports);
@@ -55,7 +56,10 @@ var BookingRequestStatusSchema = import_zod.z.enum([
55
56
  "ONGOING",
56
57
  "COMPLETED",
57
58
  "CANCELLED",
58
- "PENDING_APPROVAL"
59
+ "PENDING_APPROVAL",
60
+ "CONFIRMED",
61
+ "PENDING",
62
+ "LATE"
59
63
  ]);
60
64
  var ServiceTypeSchema = import_zod.z.enum(["SUBSCRIPTION", "ROUND_TRIP_BOOKING", "SCHEDULED_BOOKING_STATION"]);
61
65
  var getBookingRequests = async (client, status, options) => {
@@ -495,6 +499,42 @@ var updateScheduleBooking = async (client, bookingRequestId, updateData) => {
495
499
  updateData
496
500
  ).then(({ data }) => data);
497
501
  };
502
+
503
+ // src/triggerBRPayment.ts
504
+ var import_zod9 = __toESM(require("zod"));
505
+ var triggerBRPaymentSchema = import_zod9.default.object({
506
+ bookingRequestId: import_zod9.default.string().uuid(),
507
+ body: import_zod9.default.object({
508
+ scope: import_zod9.default.enum(["RENTAL", "DEPOSIT"]),
509
+ requiresActionReturnURL: import_zod9.default.string().url().optional(),
510
+ online: import_zod9.default.boolean(),
511
+ amountType: import_zod9.default.enum(["FIXED", "PERCENTAGE"]),
512
+ amountValue: import_zod9.default.number().nonnegative(),
513
+ preferredPaymentMethods: import_zod9.default.array(
514
+ import_zod9.default.object({
515
+ pspReference: import_zod9.default.string(),
516
+ amount: import_zod9.default.number().default(0)
517
+ })
518
+ ).optional(),
519
+ profileId: import_zod9.default.string().uuid()
520
+ })
521
+ });
522
+ var triggerBRPayment = async (client, bookingRequestId, body) => {
523
+ const resultPayload = triggerBRPaymentSchema.safeParse({ bookingRequestId, body });
524
+ if (!resultPayload.success) {
525
+ throw new TypeError("Invalid args", {
526
+ cause: resultPayload.error.issues
527
+ });
528
+ }
529
+ return client.post(
530
+ `boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/${bookingRequestId}/payment`,
531
+ resultPayload.data.body
532
+ ).then(({ data }) => data).catch((error) => {
533
+ throw new TypeError("Failed to trigger booking request payment", {
534
+ cause: error
535
+ });
536
+ });
537
+ };
498
538
  // Annotate the CommonJS export names for ESM import in node:
499
539
  0 && (module.exports = {
500
540
  allocateVehicle,
@@ -508,5 +548,6 @@ var updateScheduleBooking = async (client, bookingRequestId, updateData) => {
508
548
  getStations,
509
549
  getSubscriptionBookingRequestById,
510
550
  getSubscriptionBookingRequests,
551
+ triggerBRPayment,
511
552
  updateScheduleBooking
512
553
  });
package/dist/index.mjs CHANGED
@@ -8,7 +8,10 @@ var BookingRequestStatusSchema = z.enum([
8
8
  "ONGOING",
9
9
  "COMPLETED",
10
10
  "CANCELLED",
11
- "PENDING_APPROVAL"
11
+ "PENDING_APPROVAL",
12
+ "CONFIRMED",
13
+ "PENDING",
14
+ "LATE"
12
15
  ]);
13
16
  var ServiceTypeSchema = z.enum(["SUBSCRIPTION", "ROUND_TRIP_BOOKING", "SCHEDULED_BOOKING_STATION"]);
14
17
  var getBookingRequests = async (client, status, options) => {
@@ -448,6 +451,42 @@ var updateScheduleBooking = async (client, bookingRequestId, updateData) => {
448
451
  updateData
449
452
  ).then(({ data }) => data);
450
453
  };
454
+
455
+ // src/triggerBRPayment.ts
456
+ import z9 from "zod";
457
+ var triggerBRPaymentSchema = z9.object({
458
+ bookingRequestId: z9.string().uuid(),
459
+ body: z9.object({
460
+ scope: z9.enum(["RENTAL", "DEPOSIT"]),
461
+ requiresActionReturnURL: z9.string().url().optional(),
462
+ online: z9.boolean(),
463
+ amountType: z9.enum(["FIXED", "PERCENTAGE"]),
464
+ amountValue: z9.number().nonnegative(),
465
+ preferredPaymentMethods: z9.array(
466
+ z9.object({
467
+ pspReference: z9.string(),
468
+ amount: z9.number().default(0)
469
+ })
470
+ ).optional(),
471
+ profileId: z9.string().uuid()
472
+ })
473
+ });
474
+ var triggerBRPayment = async (client, bookingRequestId, body) => {
475
+ const resultPayload = triggerBRPaymentSchema.safeParse({ bookingRequestId, body });
476
+ if (!resultPayload.success) {
477
+ throw new TypeError("Invalid args", {
478
+ cause: resultPayload.error.issues
479
+ });
480
+ }
481
+ return client.post(
482
+ `boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/${bookingRequestId}/payment`,
483
+ resultPayload.data.body
484
+ ).then(({ data }) => data).catch((error) => {
485
+ throw new TypeError("Failed to trigger booking request payment", {
486
+ cause: error
487
+ });
488
+ });
489
+ };
451
490
  export {
452
491
  allocateVehicle,
453
492
  deallocateVehicle,
@@ -460,5 +499,6 @@ export {
460
499
  getStations,
461
500
  getSubscriptionBookingRequestById,
462
501
  getSubscriptionBookingRequests,
502
+ triggerBRPayment,
463
503
  updateScheduleBooking
464
504
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vulog/aima-booking",
3
- "version": "1.2.21",
3
+ "version": "1.2.23",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -19,8 +19,8 @@
19
19
  "author": "Vulog",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@vulog/aima-client": "1.2.21",
23
- "@vulog/aima-core": "1.2.21"
22
+ "@vulog/aima-client": "1.2.23",
23
+ "@vulog/aima-core": "1.2.23"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "es-toolkit": "^1.39.9",
@@ -0,0 +1,122 @@
1
+ import { describe, test, expect, vi, beforeEach } from 'vitest';
2
+ import { Client } from '@vulog/aima-client';
3
+ import { randomUUID } from 'crypto';
4
+ import { cancelBookingRequest } from './cancelBookingRequest';
5
+ import type { SATBookingRequest } from './types';
6
+
7
+ describe('cancelBookingRequest', () => {
8
+ const postMock = vi.fn();
9
+ const client = {
10
+ post: postMock,
11
+ clientOptions: {
12
+ fleetId: 'FLEET_ID',
13
+ },
14
+ } as unknown as Client;
15
+
16
+ const minimalCancelledResponse = {
17
+ id: '09c6daa5-9b4d-471c-8d2d-627d2ce7902d',
18
+ startDate: '2026-02-17T15:15:00Z',
19
+ endDate: '2026-02-19T15:15:00Z',
20
+ returnedDate: null,
21
+ profileId: '9cf8f71b-a535-4b26-b6bd-2b9856cd1cbc',
22
+ vehicleId: null,
23
+ modelId: 2597,
24
+ journeyId: null,
25
+ station: '37a505b8-a45e-4970-9adc-3bb6f177a868',
26
+ profileType: null,
27
+ entityName: null,
28
+ status: 'CANCELLED',
29
+ creationDate: '2026-02-13T14:12:04Z',
30
+ realStartDate: null,
31
+ cancellationDate: '2026-02-16T12:32:09Z',
32
+ cancelledBy: 'b60db6f0-67d3-4beb-a835-d7bc32f448c2',
33
+ fleetId: 'FLEET_ID',
34
+ userId: 'e2a19a00-87de-4e3e-8da3-6053cb137c47',
35
+ latitude: 0,
36
+ longitude: 0,
37
+ radius: 0,
38
+ serviceId: '3ef72482-94c1-40c0-a467-abffaef03d45',
39
+ warning: null,
40
+ email: null,
41
+ credits: null,
42
+ requiresActionReturnURL: null,
43
+ trip: null,
44
+ failureReason: null,
45
+ cityId: 'a91a8d56-4bf8-4a88-9afb-3f3cc255e4f8',
46
+ vehicleResidualValue: null,
47
+ price: null,
48
+ notes: null,
49
+ plannedReturnDate: null,
50
+ deliveryAddress: null,
51
+ deliveryAddressAdditionalInfo: null,
52
+ deliveryCity: null,
53
+ deliveryPostalCode: null,
54
+ dropOffStation: null,
55
+ thresholdDateLimit: null,
56
+ cancellationFeeAmount: null,
57
+ rollingContract: false,
58
+ planDurationInMonths: null,
59
+ planName: null,
60
+ parentId: null,
61
+ contractType: null,
62
+ previous: null,
63
+ customPrice: null,
64
+ productIds: ['f271997b-1184-429d-b951-bde23c1e2711'],
65
+ preallocatedVehicleId: null,
66
+ bookingReferenceId: 'p9JNDE',
67
+ pricingDetails: [
68
+ { pricingId: '0c5363cf-2763-4df7-92e4-1d66b04fc186', providerType: 'DEFAULT' },
69
+ ],
70
+ earlyCancelledByUser: false,
71
+ completed: false,
72
+ } as unknown as SATBookingRequest;
73
+
74
+ beforeEach(() => {
75
+ postMock.mockReset();
76
+ });
77
+
78
+ test('throws Invalid args when id is not a valid UUID', async () => {
79
+ await expect(cancelBookingRequest(client, 'not-a-uuid')).rejects.toThrow(TypeError);
80
+ await expect(cancelBookingRequest(client, 'not-a-uuid')).rejects.toMatchObject({
81
+ message: 'Invalid args',
82
+ });
83
+ expect(postMock).not.toHaveBeenCalled();
84
+ });
85
+
86
+ test('calls POST with correct URL and empty body and returns data', async () => {
87
+ const id = randomUUID();
88
+ postMock.mockResolvedValueOnce({ data: minimalCancelledResponse });
89
+
90
+ const result = await cancelBookingRequest(client, id);
91
+
92
+ expect(postMock).toHaveBeenCalledTimes(1);
93
+ expect(postMock).toHaveBeenCalledWith(
94
+ `/boapi/proxy/user/scheduledBooking/fleets/FLEET_ID/bookingrequests/${id}/cancel`,
95
+ {}
96
+ );
97
+ expect(result).toEqual(minimalCancelledResponse);
98
+ expect(result.status).toBe('CANCELLED');
99
+ });
100
+
101
+ test('throws when client.post rejects', async () => {
102
+ const id = randomUUID();
103
+ const networkError = new Error('Network error');
104
+ postMock.mockRejectedValueOnce(networkError);
105
+
106
+ let thrown: unknown;
107
+ try {
108
+ await cancelBookingRequest(client, id);
109
+ } catch (e) {
110
+ thrown = e;
111
+ }
112
+ expect(thrown).toBeDefined();
113
+ const err = thrown as Error & { cause?: unknown };
114
+ expect(err instanceof Error).toBe(true);
115
+ const isWrapped =
116
+ err.name === 'TypeError' &&
117
+ err.message === 'Failed to cancel booking request' &&
118
+ err.cause === networkError;
119
+ const isPropagated = err.message === 'Network error';
120
+ expect(isWrapped || isPropagated).toBe(true);
121
+ });
122
+ });
@@ -0,0 +1,28 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import z from 'zod';
3
+
4
+ import { SATBookingRequest } from './types';
5
+
6
+ const schema = z.object({
7
+ id: z.string().uuid(),
8
+ });
9
+
10
+ export const cancelBookingRequest = async (client: Client, id: string): Promise<SATBookingRequest> => {
11
+ const result = schema.safeParse({ id });
12
+ if (!result.success) {
13
+ throw new TypeError('Invalid args', {
14
+ cause: result.error.issues,
15
+ });
16
+ }
17
+ return client
18
+ .post<SATBookingRequest>(
19
+ `/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/${id}/cancel`,
20
+ {}
21
+ )
22
+ .then(({ data }) => data)
23
+ .catch((error) => {
24
+ throw new TypeError('Failed to cancel booking request', {
25
+ cause: error,
26
+ });
27
+ });
28
+ };
@@ -12,6 +12,9 @@ const BookingRequestStatusSchema = z.enum([
12
12
  'COMPLETED',
13
13
  'CANCELLED',
14
14
  'PENDING_APPROVAL',
15
+ 'CONFIRMED',
16
+ 'PENDING',
17
+ 'LATE',
15
18
  ]);
16
19
  export type BookingRequestStatus = z.infer<typeof BookingRequestStatusSchema>;
17
20
 
package/src/index.ts CHANGED
@@ -11,3 +11,4 @@ export type { IncludeStation } from './getStation';
11
11
  export { allocateVehicle } from './allocateVehicle';
12
12
  export { deallocateVehicle } from './deallocateVehicle';
13
13
  export { updateScheduleBooking } from './updateScheduleBooking';
14
+ export { triggerBRPayment } from './triggerBRPayment';
@@ -0,0 +1,135 @@
1
+ import { describe, test, expect, vi, beforeEach } from 'vitest';
2
+ import { Client } from '@vulog/aima-client';
3
+ import { randomUUID } from 'crypto';
4
+ import { releaseBRPayment } from './releaseBRPayment';
5
+ import type { SATBookingRequest } from './types';
6
+
7
+ describe('releaseBRPayment', () => {
8
+ const postMock = vi.fn();
9
+ const client = {
10
+ post: postMock,
11
+ clientOptions: {
12
+ fleetId: 'FLEET_ID',
13
+ },
14
+ } as unknown as Client;
15
+
16
+ const minimalResponse = {
17
+ id: randomUUID(),
18
+ startDate: '2026-02-17T15:15:00Z',
19
+ endDate: '2026-02-19T15:15:00Z',
20
+ returnedDate: null,
21
+ profileId: '9cf8f71b-a535-4b26-b6bd-2b9856cd1cbc',
22
+ vehicleId: null,
23
+ modelId: 2597,
24
+ journeyId: null,
25
+ station: '37a505b8-a45e-4970-9adc-3bb6f177a868',
26
+ profileType: null,
27
+ entityName: null,
28
+ status: 'CONFIRMED',
29
+ creationDate: '2026-02-13T14:12:04Z',
30
+ realStartDate: null,
31
+ cancellationDate: null,
32
+ cancelledBy: null,
33
+ fleetId: 'FLEET_ID',
34
+ userId: 'e2a19a00-87de-4e3e-8da3-6053cb137c47',
35
+ latitude: 0,
36
+ longitude: 0,
37
+ radius: 0,
38
+ serviceId: '3ef72482-94c1-40c0-a467-abffaef03d45',
39
+ warning: null,
40
+ email: null,
41
+ credits: null,
42
+ requiresActionReturnURL: null,
43
+ trip: null,
44
+ failureReason: null,
45
+ cityId: 'a91a8d56-4bf8-4a88-9afb-3f3cc255e4f8',
46
+ vehicleResidualValue: null,
47
+ price: null,
48
+ notes: null,
49
+ plannedReturnDate: null,
50
+ deliveryAddress: null,
51
+ deliveryAddressAdditionalInfo: null,
52
+ deliveryCity: null,
53
+ deliveryPostalCode: null,
54
+ dropOffStation: null,
55
+ thresholdDateLimit: null,
56
+ cancellationFeeAmount: null,
57
+ rollingContract: false,
58
+ planDurationInMonths: null,
59
+ planName: null,
60
+ parentId: null,
61
+ contractType: null,
62
+ previous: null,
63
+ customPrice: null,
64
+ productIds: ['f271997b-1184-429d-b951-bde23c1e2711'],
65
+ preallocatedVehicleId: null,
66
+ bookingReferenceId: 'p9JNDE',
67
+ pricingDetails: [
68
+ { pricingId: '0c5363cf-2763-4df7-92e4-1d66b04fc186', providerType: 'DEFAULT' },
69
+ ],
70
+ earlyCancelledByUser: false,
71
+ completed: false,
72
+ } as unknown as SATBookingRequest;
73
+
74
+ beforeEach(() => {
75
+ postMock.mockReset();
76
+ });
77
+
78
+ test('throws Invalid args when bookingRequestId is not a valid UUID', async () => {
79
+ await expect(
80
+ releaseBRPayment(client, 'not-a-uuid' as any, randomUUID())
81
+ ).rejects.toThrow(TypeError);
82
+ await expect(
83
+ releaseBRPayment(client, 'not-a-uuid' as any, randomUUID())
84
+ ).rejects.toMatchObject({ message: 'Invalid args' });
85
+ expect(postMock).not.toHaveBeenCalled();
86
+ });
87
+
88
+ test('throws Invalid args when pspReference is not a valid UUID', async () => {
89
+ await expect(
90
+ releaseBRPayment(client, randomUUID(), 'not-a-uuid')
91
+ ).rejects.toThrow(TypeError);
92
+ await expect(
93
+ releaseBRPayment(client, randomUUID(), 'not-a-uuid')
94
+ ).rejects.toMatchObject({ message: 'Invalid args' });
95
+ expect(postMock).not.toHaveBeenCalled();
96
+ });
97
+
98
+ test('calls POST with correct URL and empty body and returns data', async () => {
99
+ const bookingRequestId = randomUUID();
100
+ const pspReference = randomUUID();
101
+ postMock.mockResolvedValueOnce({ data: minimalResponse });
102
+
103
+ const result = await releaseBRPayment(client, bookingRequestId, pspReference);
104
+
105
+ expect(postMock).toHaveBeenCalledTimes(1);
106
+ expect(postMock).toHaveBeenCalledWith(
107
+ `boapi/proxy/user/scheduledBooking/fleets/FLEET_ID/bookingrequests/${bookingRequestId}/paymentintent/${pspReference}/cancel`,
108
+ {}
109
+ );
110
+ expect(result).toEqual(minimalResponse);
111
+ });
112
+
113
+ test('throws when client.post rejects', async () => {
114
+ const bookingRequestId = randomUUID();
115
+ const pspReference = randomUUID();
116
+ const networkError = new Error('Network error');
117
+ postMock.mockRejectedValueOnce(networkError);
118
+
119
+ let thrown: unknown;
120
+ try {
121
+ await releaseBRPayment(client, bookingRequestId, pspReference);
122
+ } catch (e) {
123
+ thrown = e;
124
+ }
125
+ expect(thrown).toBeDefined();
126
+ const err = thrown as Error & { cause?: unknown };
127
+ expect(err instanceof Error).toBe(true);
128
+ const isWrapped =
129
+ err.name === 'TypeError' &&
130
+ err.message === 'Failed to release booking request payment' &&
131
+ err.cause === networkError;
132
+ const isPropagated = err.message === 'Network error';
133
+ expect(isWrapped || isPropagated).toBe(true);
134
+ });
135
+ });
@@ -0,0 +1,38 @@
1
+ // /scheduledBooking/fleets/{fleetId}/bookingrequests/{id}/paymentintent/{pspReference}/cancel
2
+
3
+ import { UUID } from 'crypto';
4
+
5
+ import { Client } from '@vulog/aima-client';
6
+
7
+ import z from 'zod';
8
+
9
+ import { SATBookingRequest } from './types';
10
+
11
+ const releaseBRPaymentSchema = z.object({
12
+ bookingRequestId: z.string().uuid(),
13
+ pspReference: z.string().uuid(),
14
+ });
15
+
16
+ export const releaseBRPayment = async (
17
+ client: Client,
18
+ bookingRequestId: UUID,
19
+ pspReference: string
20
+ ): Promise<SATBookingRequest> => {
21
+ const resultPayload = releaseBRPaymentSchema.safeParse({ bookingRequestId, pspReference });
22
+ if (!resultPayload.success) {
23
+ throw new TypeError('Invalid args', {
24
+ cause: resultPayload.error.issues,
25
+ });
26
+ }
27
+ return client
28
+ .post<SATBookingRequest>(
29
+ `boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/${bookingRequestId}/paymentintent/${pspReference}/cancel`,
30
+ {}
31
+ )
32
+ .then(({ data }) => data)
33
+ .catch((error) => {
34
+ throw new TypeError('Failed to release booking request payment', {
35
+ cause: error,
36
+ });
37
+ });
38
+ };
@@ -0,0 +1,192 @@
1
+ import { describe, test, expect, vi, beforeEach } from 'vitest';
2
+ import { Client } from '@vulog/aima-client';
3
+ import { randomUUID } from 'crypto';
4
+ import { triggerBRPayment } from './triggerBRPayment';
5
+ import type { TriggerBRPaymentResponse } from './types';
6
+
7
+ describe('triggerBRPayment', () => {
8
+ const postMock = vi.fn();
9
+ const client = {
10
+ post: postMock,
11
+ clientOptions: {
12
+ fleetId: 'FLEET_ID',
13
+ },
14
+ } as unknown as Client;
15
+
16
+ const validBody = {
17
+ scope: 'RENTAL' as const,
18
+ online: true,
19
+ amountType: 'FIXED' as const,
20
+ amountValue: 0,
21
+ profileId: '16de5c48-3898-49c5-97c1-b8344c1db564',
22
+ };
23
+
24
+ const minimalTriggerBRPaymentResponse: TriggerBRPaymentResponse = {
25
+ id: randomUUID(),
26
+ cityId: 'city-1',
27
+ completed: false,
28
+ creationDate: '2017-07-02T22:58:34Z',
29
+ customPrice: null,
30
+ fleetId: 'FLEET_ID',
31
+ pricingDetails: [],
32
+ productIds: [],
33
+ profileId: '9f0fd479-28a9-4754-9c77-611ea48bfb8f',
34
+ rollingContract: false,
35
+ serviceId: '9ed7d9d4-8c64-43ef-bb3d-e2b271fed682',
36
+ startDate: '2017-08-07T07:18:40Z',
37
+ status: 'CONFIRMED',
38
+ userId: '465d4067-5332-432f-ac2c-e45af2f85694',
39
+ cancellationDate: null,
40
+ cancelledBy: null,
41
+ endDate: null,
42
+ entityName: null,
43
+ journeyId: null,
44
+ modelId: null,
45
+ profileType: null,
46
+ realStartDate: null,
47
+ returnedDate: null,
48
+ station: null,
49
+ vehicleId: null,
50
+ cancellationFeeAmount: null,
51
+ credits: [],
52
+ earlyCancelledByUser: false,
53
+ email: null,
54
+ failureReason: null,
55
+ latitude: 43.68,
56
+ longitude: 7.2,
57
+ parentId: null,
58
+ planName: null,
59
+ preallocatedVehicleId: null,
60
+ previous: null,
61
+ price: null,
62
+ radius: 30,
63
+ requiresActionReturnURL: null,
64
+ thresholdDateLimit: null,
65
+ trip: null,
66
+ warning: null,
67
+ paymentIntents: [
68
+ {
69
+ id: '0009ca58-c698-4a08-9a91-6116da1a932e',
70
+ pspName: 'STRIPE',
71
+ pspReference: 'pi_1H4QuyCOd50lRjiuhiCUMi9e',
72
+ pspPublishableKey: 'pk_test_xxx',
73
+ amount: 215.5,
74
+ currency: 'EUR',
75
+ date: '2024-05-01T12:55:02',
76
+ captureBefore: '2024-05-01T12:55:02',
77
+ status: 'PAID',
78
+ paymentMethodType: 'CREDIT_CARD',
79
+ paymentMethodPspReference: 'pm_xxx',
80
+ paymentIntentPspReference: 'pi_xxx',
81
+ number: 4564456465,
82
+ metadatas: {},
83
+ },
84
+ ],
85
+ paymentReceipts: [],
86
+ };
87
+
88
+ beforeEach(() => {
89
+ postMock.mockReset();
90
+ });
91
+
92
+ test('throws Invalid args when bookingRequestId is not a valid UUID', async () => {
93
+ await expect(
94
+ triggerBRPayment(client, 'not-a-uuid' as any, validBody)
95
+ ).rejects.toThrow(TypeError);
96
+
97
+ await expect(
98
+ triggerBRPayment(client, 'not-a-uuid' as any, validBody)
99
+ ).rejects.toMatchObject({ message: 'Invalid args' });
100
+
101
+ expect(postMock).not.toHaveBeenCalled();
102
+ });
103
+
104
+ test('throws Invalid args when body.scope is invalid', async () => {
105
+ await expect(
106
+ triggerBRPayment(client, randomUUID(), {
107
+ ...validBody,
108
+ scope: 'INVALID' as any,
109
+ })
110
+ ).rejects.toThrow(TypeError);
111
+
112
+ expect(postMock).not.toHaveBeenCalled();
113
+ });
114
+
115
+ test('throws Invalid args when body.profileId is not a valid UUID', async () => {
116
+ await expect(
117
+ triggerBRPayment(client, randomUUID(), {
118
+ ...validBody,
119
+ profileId: 'not-a-uuid',
120
+ })
121
+ ).rejects.toThrow(TypeError);
122
+
123
+ expect(postMock).not.toHaveBeenCalled();
124
+ });
125
+
126
+ test('throws Invalid args when body.amountType is invalid', async () => {
127
+ await expect(
128
+ triggerBRPayment(client, randomUUID(), {
129
+ ...validBody,
130
+ amountType: 'INVALID' as any,
131
+ })
132
+ ).rejects.toThrow(TypeError);
133
+
134
+ expect(postMock).not.toHaveBeenCalled();
135
+ });
136
+
137
+ test('calls POST with correct URL and body and returns data', async () => {
138
+ const bookingRequestId = randomUUID();
139
+ postMock.mockResolvedValueOnce({ data: minimalTriggerBRPaymentResponse });
140
+
141
+ const result = await triggerBRPayment(client, bookingRequestId, validBody);
142
+
143
+ expect(postMock).toHaveBeenCalledTimes(1);
144
+ expect(postMock).toHaveBeenCalledWith(
145
+ `boapi/proxy/user/scheduledBooking/fleets/FLEET_ID/bookingrequests/${bookingRequestId}/payment`,
146
+ validBody
147
+ );
148
+ expect(result).toEqual(minimalTriggerBRPaymentResponse);
149
+ expect(result.paymentIntents).toHaveLength(1);
150
+ expect(result.paymentIntents[0].pspName).toBe('STRIPE');
151
+ });
152
+
153
+ test('sends optional requiresActionReturnURL and preferredPaymentMethods when provided', async () => {
154
+ const bookingRequestId = randomUUID();
155
+ const bodyWithOptionals = {
156
+ ...validBody,
157
+ requiresActionReturnURL: 'https://example.com/return',
158
+ preferredPaymentMethods: [{ pspReference: 'pm_xxx', amount: 100 }],
159
+ };
160
+ postMock.mockResolvedValueOnce({ data: minimalTriggerBRPaymentResponse });
161
+
162
+ await triggerBRPayment(client, bookingRequestId, bodyWithOptionals);
163
+
164
+ expect(postMock).toHaveBeenCalledWith(
165
+ `boapi/proxy/user/scheduledBooking/fleets/FLEET_ID/bookingrequests/${bookingRequestId}/payment`,
166
+ bodyWithOptionals
167
+ );
168
+ });
169
+
170
+ test('throws when client.post rejects', async () => {
171
+ const bookingRequestId = randomUUID();
172
+ const networkError = new Error('Network error');
173
+ postMock.mockRejectedValueOnce(networkError);
174
+
175
+ let thrown: unknown;
176
+ try {
177
+ await triggerBRPayment(client, bookingRequestId, validBody);
178
+ } catch (e) {
179
+ thrown = e;
180
+ }
181
+ expect(thrown).toBeDefined();
182
+ const err = thrown as Error & { cause?: unknown };
183
+ expect(err instanceof Error).toBe(true);
184
+ // Implementation may wrap in TypeError('Failed to trigger booking request payment', { cause })
185
+ const isWrapped =
186
+ err.name === 'TypeError' &&
187
+ err.message === 'Failed to trigger booking request payment' &&
188
+ err.cause === networkError;
189
+ const isPropagated = err.message === 'Network error';
190
+ expect(isWrapped || isPropagated).toBe(true);
191
+ });
192
+ });
@@ -0,0 +1,52 @@
1
+ import { UUID } from 'crypto';
2
+
3
+ import { Client } from '@vulog/aima-client';
4
+
5
+ import z from 'zod';
6
+
7
+ import { TriggerBRPaymentResponse } from './types';
8
+
9
+ const triggerBRPaymentSchema = z.object({
10
+ bookingRequestId: z.string().uuid(),
11
+ body: z.object({
12
+ scope: z.enum(['RENTAL', 'DEPOSIT']),
13
+ requiresActionReturnURL: z.string().url().optional(),
14
+ online: z.boolean(),
15
+ amountType: z.enum(['FIXED', 'PERCENTAGE']),
16
+ amountValue: z.number().nonnegative(),
17
+ preferredPaymentMethods: z
18
+ .array(
19
+ z.object({
20
+ pspReference: z.string(),
21
+ amount: z.number().default(0),
22
+ })
23
+ )
24
+ .optional(),
25
+ profileId: z.string().uuid(),
26
+ }),
27
+ });
28
+
29
+ // /scheduledBooking/fleets/{fleetId}/bookingrequests/{id}/payment
30
+ export const triggerBRPayment = async (
31
+ client: Client,
32
+ bookingRequestId: UUID,
33
+ body: z.infer<typeof triggerBRPaymentSchema>['body']
34
+ ): Promise<TriggerBRPaymentResponse> => {
35
+ const resultPayload = triggerBRPaymentSchema.safeParse({ bookingRequestId, body });
36
+ if (!resultPayload.success) {
37
+ throw new TypeError('Invalid args', {
38
+ cause: resultPayload.error.issues,
39
+ });
40
+ }
41
+ return client
42
+ .post<TriggerBRPaymentResponse>(
43
+ `boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/${bookingRequestId}/payment`,
44
+ resultPayload.data.body
45
+ )
46
+ .then(({ data }) => data)
47
+ .catch((error) => {
48
+ throw new TypeError('Failed to trigger booking request payment', {
49
+ cause: error,
50
+ });
51
+ });
52
+ };
package/src/types.ts CHANGED
@@ -15,6 +15,54 @@ export type PaymentReceipts = {
15
15
  };
16
16
  };
17
17
 
18
+ /** Payment intent or receipt item as returned by trigger BR payment (and similar payment endpoints). */
19
+ export type BRPaymentItem = {
20
+ id: string;
21
+ pspName: string;
22
+ pspReference: string;
23
+ pspPublishableKey: string;
24
+ amount: number;
25
+ currency: string;
26
+ date: string;
27
+ captureBefore: string;
28
+ status: string;
29
+ paymentMethodType: string;
30
+ paymentMethodPspReference: string;
31
+ paymentIntentPspReference: string;
32
+ number: number;
33
+ code?: string;
34
+ declineCode?: string;
35
+ pspClientSecret?: string;
36
+ reason?: string;
37
+ note?: string;
38
+ nextAction?: {
39
+ nextActionRedirectUrl: {
40
+ url: string;
41
+ method: string;
42
+ data: Record<string, string>;
43
+ };
44
+ type: string;
45
+ };
46
+ metadatas: Record<string, string>;
47
+ };
48
+
49
+ /** Credit entry in a booking request (e.g. trigger BR payment response). */
50
+ export type BookingCredit = {
51
+ id: string;
52
+ fleetId: string;
53
+ amount: number;
54
+ availableAmount: number;
55
+ status: string;
56
+ walletId: string;
57
+ date: string;
58
+ };
59
+
60
+ /** Preferred payment method entry in request/response. */
61
+ export type PreferredPaymentMethod = {
62
+ pspReference: string;
63
+ amount: number;
64
+ };
65
+
18
66
  export type CustomPrice = {
19
67
  id: string;
20
68
  fleetId: string;
@@ -104,6 +152,14 @@ export type SATBookingRequest = BaseBookingRequest & {
104
152
  warning: string | null;
105
153
  };
106
154
 
155
+ /** Response of the trigger BR payment endpoint (booking request + payment intents/receipts). */
156
+ export type TriggerBRPaymentResponse = Omit<SATBookingRequest, 'credits'> & {
157
+ paymentIntents: BRPaymentItem[];
158
+ paymentReceipts: BRPaymentItem[];
159
+ credits: BookingCredit[];
160
+ preferredPaymentMethods?: PreferredPaymentMethod[];
161
+ };
162
+
107
163
  // Station types
108
164
  export type GeoInfo = {
109
165
  name: string;