@vulog/aima-booking 1.2.22 → 1.2.25

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
@@ -261,7 +261,7 @@ declare const triggerBRPaymentSchema: z$1.ZodObject<{
261
261
  requiresActionReturnURL: z$1.ZodOptional<z$1.ZodString>;
262
262
  online: z$1.ZodBoolean;
263
263
  amountType: z$1.ZodEnum<["FIXED", "PERCENTAGE"]>;
264
- amountValue: z$1.ZodOptional<z$1.ZodNumber>;
264
+ amountValue: z$1.ZodNumber;
265
265
  preferredPaymentMethods: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
266
266
  pspReference: z$1.ZodString;
267
267
  amount: z$1.ZodDefault<z$1.ZodNumber>;
@@ -278,8 +278,8 @@ declare const triggerBRPaymentSchema: z$1.ZodObject<{
278
278
  scope: "RENTAL" | "DEPOSIT";
279
279
  online: boolean;
280
280
  amountType: "FIXED" | "PERCENTAGE";
281
+ amountValue: number;
281
282
  requiresActionReturnURL?: string | undefined;
282
- amountValue?: number | undefined;
283
283
  preferredPaymentMethods?: {
284
284
  pspReference: string;
285
285
  amount: number;
@@ -289,8 +289,8 @@ declare const triggerBRPaymentSchema: z$1.ZodObject<{
289
289
  scope: "RENTAL" | "DEPOSIT";
290
290
  online: boolean;
291
291
  amountType: "FIXED" | "PERCENTAGE";
292
+ amountValue: number;
292
293
  requiresActionReturnURL?: string | undefined;
293
- amountValue?: number | undefined;
294
294
  preferredPaymentMethods?: {
295
295
  pspReference: string;
296
296
  amount?: number | undefined;
@@ -302,8 +302,8 @@ declare const triggerBRPaymentSchema: z$1.ZodObject<{
302
302
  scope: "RENTAL" | "DEPOSIT";
303
303
  online: boolean;
304
304
  amountType: "FIXED" | "PERCENTAGE";
305
+ amountValue: number;
305
306
  requiresActionReturnURL?: string | undefined;
306
- amountValue?: number | undefined;
307
307
  preferredPaymentMethods?: {
308
308
  pspReference: string;
309
309
  amount: number;
@@ -316,8 +316,8 @@ declare const triggerBRPaymentSchema: z$1.ZodObject<{
316
316
  scope: "RENTAL" | "DEPOSIT";
317
317
  online: boolean;
318
318
  amountType: "FIXED" | "PERCENTAGE";
319
+ amountValue: number;
319
320
  requiresActionReturnURL?: string | undefined;
320
- amountValue?: number | undefined;
321
321
  preferredPaymentMethods?: {
322
322
  pspReference: string;
323
323
  amount?: number | undefined;
@@ -327,4 +327,10 @@ declare const triggerBRPaymentSchema: z$1.ZodObject<{
327
327
  }>;
328
328
  declare const triggerBRPayment: (client: Client, bookingRequestId: UUID, body: z$1.infer<typeof triggerBRPaymentSchema>["body"]) => Promise<TriggerBRPaymentResponse>;
329
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 };
330
+ declare const getBookingRequestsByUserId: (client: Client, userId: string) => Promise<BookingRequest[]>;
331
+
332
+ declare const releaseBRPayment: (client: Client, bookingRequestId: UUID, pspReference: string) => Promise<SATBookingRequest>;
333
+
334
+ declare const cancelBookingRequest: (client: Client, id: string) => Promise<SATBookingRequest>;
335
+
336
+ 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, cancelBookingRequest, deallocateVehicle, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getBookingRequestsByUserId, getSATBookingRequests, getScheduleBookingRequests, getStationById, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, releaseBRPayment, triggerBRPayment, updateScheduleBooking };
package/dist/index.d.ts CHANGED
@@ -261,7 +261,7 @@ declare const triggerBRPaymentSchema: z$1.ZodObject<{
261
261
  requiresActionReturnURL: z$1.ZodOptional<z$1.ZodString>;
262
262
  online: z$1.ZodBoolean;
263
263
  amountType: z$1.ZodEnum<["FIXED", "PERCENTAGE"]>;
264
- amountValue: z$1.ZodOptional<z$1.ZodNumber>;
264
+ amountValue: z$1.ZodNumber;
265
265
  preferredPaymentMethods: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
266
266
  pspReference: z$1.ZodString;
267
267
  amount: z$1.ZodDefault<z$1.ZodNumber>;
@@ -278,8 +278,8 @@ declare const triggerBRPaymentSchema: z$1.ZodObject<{
278
278
  scope: "RENTAL" | "DEPOSIT";
279
279
  online: boolean;
280
280
  amountType: "FIXED" | "PERCENTAGE";
281
+ amountValue: number;
281
282
  requiresActionReturnURL?: string | undefined;
282
- amountValue?: number | undefined;
283
283
  preferredPaymentMethods?: {
284
284
  pspReference: string;
285
285
  amount: number;
@@ -289,8 +289,8 @@ declare const triggerBRPaymentSchema: z$1.ZodObject<{
289
289
  scope: "RENTAL" | "DEPOSIT";
290
290
  online: boolean;
291
291
  amountType: "FIXED" | "PERCENTAGE";
292
+ amountValue: number;
292
293
  requiresActionReturnURL?: string | undefined;
293
- amountValue?: number | undefined;
294
294
  preferredPaymentMethods?: {
295
295
  pspReference: string;
296
296
  amount?: number | undefined;
@@ -302,8 +302,8 @@ declare const triggerBRPaymentSchema: z$1.ZodObject<{
302
302
  scope: "RENTAL" | "DEPOSIT";
303
303
  online: boolean;
304
304
  amountType: "FIXED" | "PERCENTAGE";
305
+ amountValue: number;
305
306
  requiresActionReturnURL?: string | undefined;
306
- amountValue?: number | undefined;
307
307
  preferredPaymentMethods?: {
308
308
  pspReference: string;
309
309
  amount: number;
@@ -316,8 +316,8 @@ declare const triggerBRPaymentSchema: z$1.ZodObject<{
316
316
  scope: "RENTAL" | "DEPOSIT";
317
317
  online: boolean;
318
318
  amountType: "FIXED" | "PERCENTAGE";
319
+ amountValue: number;
319
320
  requiresActionReturnURL?: string | undefined;
320
- amountValue?: number | undefined;
321
321
  preferredPaymentMethods?: {
322
322
  pspReference: string;
323
323
  amount?: number | undefined;
@@ -327,4 +327,10 @@ declare const triggerBRPaymentSchema: z$1.ZodObject<{
327
327
  }>;
328
328
  declare const triggerBRPayment: (client: Client, bookingRequestId: UUID, body: z$1.infer<typeof triggerBRPaymentSchema>["body"]) => Promise<TriggerBRPaymentResponse>;
329
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 };
330
+ declare const getBookingRequestsByUserId: (client: Client, userId: string) => Promise<BookingRequest[]>;
331
+
332
+ declare const releaseBRPayment: (client: Client, bookingRequestId: UUID, pspReference: string) => Promise<SATBookingRequest>;
333
+
334
+ declare const cancelBookingRequest: (client: Client, id: string) => Promise<SATBookingRequest>;
335
+
336
+ 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, cancelBookingRequest, deallocateVehicle, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getBookingRequestsByUserId, getSATBookingRequests, getScheduleBookingRequests, getStationById, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, releaseBRPayment, triggerBRPayment, updateScheduleBooking };
package/dist/index.js CHANGED
@@ -31,16 +31,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  allocateVehicle: () => allocateVehicle,
34
+ cancelBookingRequest: () => cancelBookingRequest,
34
35
  deallocateVehicle: () => deallocateVehicle,
35
36
  getBookingRequestById: () => getBookingRequestById,
36
37
  getBookingRequestByTrip: () => getBookingRequestByTrip,
37
38
  getBookingRequests: () => getBookingRequests,
39
+ getBookingRequestsByUserId: () => getBookingRequestsByUserId,
38
40
  getSATBookingRequests: () => getSATBookingRequests,
39
41
  getScheduleBookingRequests: () => getScheduleBookingRequests,
40
42
  getStationById: () => getStationById,
41
43
  getStations: () => getStations,
42
44
  getSubscriptionBookingRequestById: () => getSubscriptionBookingRequestById,
43
45
  getSubscriptionBookingRequests: () => getSubscriptionBookingRequests,
46
+ releaseBRPayment: () => releaseBRPayment,
44
47
  triggerBRPayment: () => triggerBRPayment,
45
48
  updateScheduleBooking: () => updateScheduleBooking
46
49
  });
@@ -509,7 +512,7 @@ var triggerBRPaymentSchema = import_zod9.default.object({
509
512
  requiresActionReturnURL: import_zod9.default.string().url().optional(),
510
513
  online: import_zod9.default.boolean(),
511
514
  amountType: import_zod9.default.enum(["FIXED", "PERCENTAGE"]),
512
- amountValue: import_zod9.default.number().nonnegative().optional(),
515
+ amountValue: import_zod9.default.number().nonnegative(),
513
516
  preferredPaymentMethods: import_zod9.default.array(
514
517
  import_zod9.default.object({
515
518
  pspReference: import_zod9.default.string(),
@@ -535,19 +538,89 @@ var triggerBRPayment = async (client, bookingRequestId, body) => {
535
538
  });
536
539
  });
537
540
  };
541
+
542
+ // src/getBookingRequestsByUserId.ts
543
+ var import_zod10 = require("zod");
544
+ var schema2 = import_zod10.z.object({
545
+ userId: import_zod10.z.string().trim().min(1).uuid()
546
+ });
547
+ var getBookingRequestsByUserId = async (client, userId) => {
548
+ const result = schema2.safeParse({ userId });
549
+ if (!result.success) {
550
+ throw new TypeError("Invalid userId", {
551
+ cause: result.error.issues
552
+ });
553
+ }
554
+ return client.get(
555
+ `/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/users/${userId}`
556
+ ).then(({ data }) => data).catch((error) => {
557
+ if (error.formattedError?.status === 404) {
558
+ return [];
559
+ }
560
+ throw error;
561
+ });
562
+ };
563
+
564
+ // src/releaseBRPayment.ts
565
+ var import_zod11 = __toESM(require("zod"));
566
+ var releaseBRPaymentSchema = import_zod11.default.object({
567
+ bookingRequestId: import_zod11.default.string().uuid(),
568
+ pspReference: import_zod11.default.string().uuid()
569
+ });
570
+ var releaseBRPayment = async (client, bookingRequestId, pspReference) => {
571
+ const resultPayload = releaseBRPaymentSchema.safeParse({ bookingRequestId, pspReference });
572
+ if (!resultPayload.success) {
573
+ throw new TypeError("Invalid args", {
574
+ cause: resultPayload.error.issues
575
+ });
576
+ }
577
+ return client.post(
578
+ `boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/${bookingRequestId}/paymentintent/${pspReference}/cancel`,
579
+ {}
580
+ ).then(({ data }) => data).catch((error) => {
581
+ throw new TypeError("Failed to release booking request payment", {
582
+ cause: error
583
+ });
584
+ });
585
+ };
586
+
587
+ // src/cancelBookingRequest.ts
588
+ var import_zod12 = __toESM(require("zod"));
589
+ var schema3 = import_zod12.default.object({
590
+ id: import_zod12.default.string().uuid()
591
+ });
592
+ var cancelBookingRequest = async (client, id) => {
593
+ const result = schema3.safeParse({ id });
594
+ if (!result.success) {
595
+ throw new TypeError("Invalid args", {
596
+ cause: result.error.issues
597
+ });
598
+ }
599
+ return client.post(
600
+ `/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/cancel/${id}`,
601
+ {}
602
+ ).then(({ data }) => data).catch((error) => {
603
+ throw new TypeError("Failed to cancel booking request", {
604
+ cause: error
605
+ });
606
+ });
607
+ };
538
608
  // Annotate the CommonJS export names for ESM import in node:
539
609
  0 && (module.exports = {
540
610
  allocateVehicle,
611
+ cancelBookingRequest,
541
612
  deallocateVehicle,
542
613
  getBookingRequestById,
543
614
  getBookingRequestByTrip,
544
615
  getBookingRequests,
616
+ getBookingRequestsByUserId,
545
617
  getSATBookingRequests,
546
618
  getScheduleBookingRequests,
547
619
  getStationById,
548
620
  getStations,
549
621
  getSubscriptionBookingRequestById,
550
622
  getSubscriptionBookingRequests,
623
+ releaseBRPayment,
551
624
  triggerBRPayment,
552
625
  updateScheduleBooking
553
626
  });
package/dist/index.mjs CHANGED
@@ -461,7 +461,7 @@ var triggerBRPaymentSchema = z9.object({
461
461
  requiresActionReturnURL: z9.string().url().optional(),
462
462
  online: z9.boolean(),
463
463
  amountType: z9.enum(["FIXED", "PERCENTAGE"]),
464
- amountValue: z9.number().nonnegative().optional(),
464
+ amountValue: z9.number().nonnegative(),
465
465
  preferredPaymentMethods: z9.array(
466
466
  z9.object({
467
467
  pspReference: z9.string(),
@@ -487,18 +487,88 @@ var triggerBRPayment = async (client, bookingRequestId, body) => {
487
487
  });
488
488
  });
489
489
  };
490
+
491
+ // src/getBookingRequestsByUserId.ts
492
+ import { z as z10 } from "zod";
493
+ var schema2 = z10.object({
494
+ userId: z10.string().trim().min(1).uuid()
495
+ });
496
+ var getBookingRequestsByUserId = async (client, userId) => {
497
+ const result = schema2.safeParse({ userId });
498
+ if (!result.success) {
499
+ throw new TypeError("Invalid userId", {
500
+ cause: result.error.issues
501
+ });
502
+ }
503
+ return client.get(
504
+ `/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/users/${userId}`
505
+ ).then(({ data }) => data).catch((error) => {
506
+ if (error.formattedError?.status === 404) {
507
+ return [];
508
+ }
509
+ throw error;
510
+ });
511
+ };
512
+
513
+ // src/releaseBRPayment.ts
514
+ import z11 from "zod";
515
+ var releaseBRPaymentSchema = z11.object({
516
+ bookingRequestId: z11.string().uuid(),
517
+ pspReference: z11.string().uuid()
518
+ });
519
+ var releaseBRPayment = async (client, bookingRequestId, pspReference) => {
520
+ const resultPayload = releaseBRPaymentSchema.safeParse({ bookingRequestId, pspReference });
521
+ if (!resultPayload.success) {
522
+ throw new TypeError("Invalid args", {
523
+ cause: resultPayload.error.issues
524
+ });
525
+ }
526
+ return client.post(
527
+ `boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/${bookingRequestId}/paymentintent/${pspReference}/cancel`,
528
+ {}
529
+ ).then(({ data }) => data).catch((error) => {
530
+ throw new TypeError("Failed to release booking request payment", {
531
+ cause: error
532
+ });
533
+ });
534
+ };
535
+
536
+ // src/cancelBookingRequest.ts
537
+ import z12 from "zod";
538
+ var schema3 = z12.object({
539
+ id: z12.string().uuid()
540
+ });
541
+ var cancelBookingRequest = async (client, id) => {
542
+ const result = schema3.safeParse({ id });
543
+ if (!result.success) {
544
+ throw new TypeError("Invalid args", {
545
+ cause: result.error.issues
546
+ });
547
+ }
548
+ return client.post(
549
+ `/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/cancel/${id}`,
550
+ {}
551
+ ).then(({ data }) => data).catch((error) => {
552
+ throw new TypeError("Failed to cancel booking request", {
553
+ cause: error
554
+ });
555
+ });
556
+ };
490
557
  export {
491
558
  allocateVehicle,
559
+ cancelBookingRequest,
492
560
  deallocateVehicle,
493
561
  getBookingRequestById,
494
562
  getBookingRequestByTrip,
495
563
  getBookingRequests,
564
+ getBookingRequestsByUserId,
496
565
  getSATBookingRequests,
497
566
  getScheduleBookingRequests,
498
567
  getStationById,
499
568
  getStations,
500
569
  getSubscriptionBookingRequestById,
501
570
  getSubscriptionBookingRequests,
571
+ releaseBRPayment,
502
572
  triggerBRPayment,
503
573
  updateScheduleBooking
504
574
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vulog/aima-booking",
3
- "version": "1.2.22",
3
+ "version": "1.2.25",
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.22",
23
- "@vulog/aima-core": "1.2.22"
22
+ "@vulog/aima-client": "1.2.25",
23
+ "@vulog/aima-core": "1.2.25"
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/cancel/${id}`,
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/cancel/${id}`,
20
+ {}
21
+ )
22
+ .then(({ data }) => data)
23
+ .catch((error) => {
24
+ throw new TypeError('Failed to cancel booking request', {
25
+ cause: error,
26
+ });
27
+ });
28
+ };
@@ -0,0 +1,102 @@
1
+ import { describe, test, expect, vi, beforeEach } from 'vitest';
2
+ import { getBookingRequestsByUserId } from './getBookingRequestsByUserId';
3
+ import { Client } from '@vulog/aima-client';
4
+ import { randomUUID } from 'crypto';
5
+
6
+ describe('getBookingRequestsByUserId', () => {
7
+ const getMock = vi.fn();
8
+ const client = {
9
+ get: getMock,
10
+ clientOptions: {
11
+ fleetId: 'FLEET_ID',
12
+ },
13
+ } as unknown as Client;
14
+
15
+ beforeEach(() => {
16
+ getMock.mockReset();
17
+ });
18
+
19
+ test('invalid userId (empty string)', async () => {
20
+ const rejects = expect(() => getBookingRequestsByUserId(client, '')).rejects;
21
+ await rejects.toThrow(TypeError);
22
+ await rejects.toThrow('Invalid userId');
23
+ await rejects.toSatisfy((error: Error & { cause?: unknown }) => {
24
+ expect(error).toHaveProperty('cause');
25
+ return true;
26
+ });
27
+ });
28
+
29
+ test('invalid userId (not a UUID)', async () => {
30
+ const rejects = expect(() => getBookingRequestsByUserId(client, 'not-a-uuid')).rejects;
31
+ await rejects.toThrow(TypeError);
32
+ await rejects.toThrow('Invalid userId');
33
+ await rejects.toSatisfy((error: Error & { cause?: unknown }) => {
34
+ expect(error).toHaveProperty('cause');
35
+ const issues = error.cause as Array<{ code?: string }>;
36
+ expect(issues?.some((e) => e.code === 'invalid_string')).toBe(true);
37
+ return true;
38
+ });
39
+ });
40
+
41
+ test('invalid userId (whitespace only)', async () => {
42
+ const rejects = expect(() => getBookingRequestsByUserId(client, ' ')).rejects;
43
+ await rejects.toThrow(TypeError);
44
+ await rejects.toThrow('Invalid userId');
45
+ });
46
+
47
+ test('call returns booking requests', async () => {
48
+ const userId = randomUUID();
49
+ const data = [
50
+ {
51
+ id: randomUUID(),
52
+ status: 'CONFIRMED',
53
+ creationDate: '2024-11-14T13:27:30Z',
54
+ fleetId: 'VULOG-FRNCE',
55
+ userId,
56
+ cityId: 'a91a8d56-4bf8-4a88-9afb-3f3cc255e4f8',
57
+ completed: false,
58
+ },
59
+ ];
60
+ getMock.mockResolvedValueOnce({ data });
61
+
62
+ const result = await getBookingRequestsByUserId(client, userId);
63
+
64
+ expect(getMock).toHaveBeenCalledWith(
65
+ `/user/scheduledBooking/fleets/FLEET_ID/bookingrequests/users/${userId}`
66
+ );
67
+ expect(result).toEqual(data);
68
+ });
69
+
70
+ test('call with valid UUID returns empty array when 404', async () => {
71
+ const userId = randomUUID();
72
+ getMock.mockRejectedValueOnce({
73
+ formattedError: { status: 404 },
74
+ });
75
+
76
+ const result = await getBookingRequestsByUserId(client, userId);
77
+
78
+ expect(getMock).toHaveBeenCalledWith(
79
+ `/user/scheduledBooking/fleets/FLEET_ID/bookingrequests/users/${userId}`
80
+ );
81
+ expect(result).toEqual([]);
82
+ });
83
+
84
+ test('rethrows on non-404 error', async () => {
85
+ const userId = randomUUID();
86
+ const err = new Error('Network error');
87
+ getMock.mockRejectedValueOnce(err);
88
+
89
+ await expect(getBookingRequestsByUserId(client, userId)).rejects.toThrow('Network error');
90
+ });
91
+
92
+ test('rethrows when formattedError status is not 404', async () => {
93
+ const userId = randomUUID();
94
+ getMock.mockRejectedValueOnce({
95
+ formattedError: { status: 500 },
96
+ });
97
+
98
+ await expect(getBookingRequestsByUserId(client, userId)).rejects.toMatchObject({
99
+ formattedError: { status: 500 },
100
+ });
101
+ });
102
+ });
@@ -0,0 +1,28 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ import { BookingRequest } from './types';
5
+
6
+ const schema = z.object({
7
+ userId: z.string().trim().min(1).uuid(),
8
+ });
9
+
10
+ export const getBookingRequestsByUserId = async (client: Client, userId: string): Promise<BookingRequest[]> => {
11
+ const result = schema.safeParse({ userId });
12
+ if (!result.success) {
13
+ throw new TypeError('Invalid userId', {
14
+ cause: result.error.issues,
15
+ });
16
+ }
17
+ return client
18
+ .get<BookingRequest[]>(
19
+ `/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/users/${userId}`
20
+ )
21
+ .then(({ data }) => data)
22
+ .catch((error) => {
23
+ if (error.formattedError?.status === 404) {
24
+ return [];
25
+ }
26
+ throw error;
27
+ });
28
+ };
package/src/index.ts CHANGED
@@ -12,3 +12,6 @@ export { allocateVehicle } from './allocateVehicle';
12
12
  export { deallocateVehicle } from './deallocateVehicle';
13
13
  export { updateScheduleBooking } from './updateScheduleBooking';
14
14
  export { triggerBRPayment } from './triggerBRPayment';
15
+ export { getBookingRequestsByUserId } from './getBookingRequestsByUserId';
16
+ export { releaseBRPayment } from './releaseBRPayment';
17
+ export { cancelBookingRequest } from './cancelBookingRequest';
@@ -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
+ };
@@ -13,7 +13,7 @@ const triggerBRPaymentSchema = z.object({
13
13
  requiresActionReturnURL: z.string().url().optional(),
14
14
  online: z.boolean(),
15
15
  amountType: z.enum(['FIXED', 'PERCENTAGE']),
16
- amountValue: z.number().nonnegative().optional(),
16
+ amountValue: z.number().nonnegative(),
17
17
  preferredPaymentMethods: z
18
18
  .array(
19
19
  z.object({