@vulog/aima-booking 1.2.33 → 1.2.35
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/README.md +103 -0
- package/dist/index.cjs +82 -6
- package/dist/index.d.cts +125 -1
- package/dist/index.d.mts +125 -1
- package/dist/index.mjs +77 -7
- package/package.json +3 -3
- package/src/getAdditionalDrivers.test.ts +61 -0
- package/src/getAdditionalDrivers.ts +23 -0
- package/src/getAvailableVehicles.test.ts +53 -0
- package/src/getBookingRequest.test.ts +72 -1
- package/src/getBookingRequest.ts +15 -1
- package/src/getDigitalContracts.test.ts +72 -0
- package/src/getDigitalContracts.ts +26 -0
- package/src/getSlaves.test.ts +60 -0
- package/src/getSlaves.ts +24 -0
- package/src/getSubscriptionsByUserId.test.ts +96 -0
- package/src/getSubscriptionsByUserId.ts +27 -0
- package/src/index.ts +11 -1
- package/src/submitCancellationRequest.test.ts +81 -0
- package/src/submitCancellationRequest.ts +38 -0
- package/src/types.ts +117 -0
package/dist/index.mjs
CHANGED
|
@@ -148,6 +148,11 @@ const getSubscriptionBookingRequestById = async (client, id) => {
|
|
|
148
148
|
...data
|
|
149
149
|
}));
|
|
150
150
|
};
|
|
151
|
+
const getScheduledBookingById = async (client, bookingId) => {
|
|
152
|
+
const result = z.string().trim().min(1).uuid().safeParse(bookingId);
|
|
153
|
+
if (!result.success) throw new TypeError("Invalid bookingId", { cause: result.error.issues });
|
|
154
|
+
return client.get(`/boapi/proxy/user/scheduledBooking/by-service/fleets/${client.clientOptions.fleetId}/bookingrequests/${bookingId}`).then(({ data }) => data);
|
|
155
|
+
};
|
|
151
156
|
//#endregion
|
|
152
157
|
//#region src/getAvailableVehicles.ts
|
|
153
158
|
/** ISO date-time without milliseconds (e.g. 2025-02-10T12:00:00Z or 2025-02-10T12:00:00+01:00). */
|
|
@@ -328,7 +333,7 @@ const deallocateVehicle = async (client, bookingRequestId, vehicleId) => {
|
|
|
328
333
|
};
|
|
329
334
|
//#endregion
|
|
330
335
|
//#region src/updateScheduleBooking.ts
|
|
331
|
-
const schema$
|
|
336
|
+
const schema$7 = z$1.object({
|
|
332
337
|
id: z$1.string(),
|
|
333
338
|
startDate: z$1.string().refine((date) => !Number.isNaN(Date.parse(date)), { message: "Invalid date" }).optional(),
|
|
334
339
|
latitude: z$1.number().min(-90).max(90).optional(),
|
|
@@ -350,7 +355,7 @@ const schema$2 = z$1.object({
|
|
|
350
355
|
plannedReturnDate: z$1.string().refine((date) => !Number.isNaN(Date.parse(date)), { message: "Invalid date" }).optional()
|
|
351
356
|
});
|
|
352
357
|
const updateScheduleBooking = async (client, bookingRequestId, updateData) => {
|
|
353
|
-
const result = schema$
|
|
358
|
+
const result = schema$7.safeParse({
|
|
354
359
|
id: bookingRequestId,
|
|
355
360
|
...updateData
|
|
356
361
|
});
|
|
@@ -386,9 +391,9 @@ const triggerBRPayment = async (client, bookingRequestId, body) => {
|
|
|
386
391
|
};
|
|
387
392
|
//#endregion
|
|
388
393
|
//#region src/getBookingRequestsByUserId.ts
|
|
389
|
-
const schema$
|
|
394
|
+
const schema$6 = z.object({ userId: z.string().trim().min(1).uuid() });
|
|
390
395
|
const getBookingRequestsByUserId = async (client, userId) => {
|
|
391
|
-
const result = schema$
|
|
396
|
+
const result = schema$6.safeParse({ userId });
|
|
392
397
|
if (!result.success) throw new TypeError("Invalid userId", { cause: result.error.issues });
|
|
393
398
|
return client.get(`/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/users/${userId}`).then(({ data }) => data).catch((error) => {
|
|
394
399
|
if (error.formattedError?.status === 404) return [];
|
|
@@ -413,15 +418,80 @@ const releaseBRPayment = async (client, bookingRequestId, pspReference) => {
|
|
|
413
418
|
};
|
|
414
419
|
//#endregion
|
|
415
420
|
//#region src/cancelBookingRequest.ts
|
|
416
|
-
const schema = z$1.object({ id: z$1.string().uuid() });
|
|
421
|
+
const schema$5 = z$1.object({ id: z$1.string().uuid() });
|
|
417
422
|
const cancelBookingRequest = async (client, id) => {
|
|
418
|
-
const result = schema.safeParse({ id });
|
|
423
|
+
const result = schema$5.safeParse({ id });
|
|
419
424
|
if (!result.success) throw new TypeError("Invalid args", { cause: result.error.issues });
|
|
420
425
|
return client.post(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests/cancel/${id}`, {}).then(({ data }) => data).catch((error) => {
|
|
421
426
|
throw new TypeError("Failed to cancel booking request", { cause: error });
|
|
422
427
|
});
|
|
423
428
|
};
|
|
424
429
|
//#endregion
|
|
430
|
+
//#region src/getDigitalContracts.ts
|
|
431
|
+
const schema$4 = z.object({ bookingId: z.string().trim().min(1) });
|
|
432
|
+
const getDigitalContracts = async (client, bookingId, status = "SIGNED") => {
|
|
433
|
+
const result = schema$4.safeParse({ bookingId });
|
|
434
|
+
if (!result.success) throw new TypeError("Invalid args", { cause: result.error.issues });
|
|
435
|
+
return client.get(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/subscription/bookingrequests/${result.data.bookingId}/digitalContracts?status=${encodeURIComponent(status)}`).then(({ data }) => data);
|
|
436
|
+
};
|
|
437
|
+
//#endregion
|
|
438
|
+
//#region src/getAdditionalDrivers.ts
|
|
439
|
+
const schema$3 = z.object({ parentId: z.string().trim().min(1) });
|
|
440
|
+
const getAdditionalDrivers = async (client, parentId) => {
|
|
441
|
+
const result = schema$3.safeParse({ parentId });
|
|
442
|
+
if (!result.success) throw new TypeError("Invalid parentId", { cause: result.error.issues });
|
|
443
|
+
return client.get(`/boapi/proxy/user/fleets/${client.clientOptions.fleetId}/bookingrequests/${parentId}/additionalDrivers`).then(({ data }) => data);
|
|
444
|
+
};
|
|
445
|
+
//#endregion
|
|
446
|
+
//#region src/getSlaves.ts
|
|
447
|
+
const schema$2 = z.object({
|
|
448
|
+
parentId: z.string().trim().min(1),
|
|
449
|
+
status: z.enum(["ONGOING, COMPLETED", "UPCOMING"])
|
|
450
|
+
});
|
|
451
|
+
const getSlaves = async (client, parentId, status) => {
|
|
452
|
+
const result = schema$2.safeParse({
|
|
453
|
+
parentId,
|
|
454
|
+
status
|
|
455
|
+
});
|
|
456
|
+
if (!result.success) throw new TypeError("Invalid bookingId", { cause: result.error.issues });
|
|
457
|
+
return client.get(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/subscription/bookingRequests/${parentId}/bookingRequestsSlave?bookingStatus=${status}`).then(({ data }) => data);
|
|
458
|
+
};
|
|
459
|
+
//#endregion
|
|
460
|
+
//#region src/getSubscriptionsByUserId.ts
|
|
461
|
+
const schema$1 = z.object({
|
|
462
|
+
userId: z.string().trim().min(1).uuid(),
|
|
463
|
+
active: z.boolean().optional().default(true)
|
|
464
|
+
});
|
|
465
|
+
const getSubscriptionsByUserId = async (client, userId, active = true) => {
|
|
466
|
+
const result = schema$1.safeParse({
|
|
467
|
+
userId,
|
|
468
|
+
active
|
|
469
|
+
});
|
|
470
|
+
if (!result.success) throw new TypeError("Invalid userId", { cause: result.error.issues });
|
|
471
|
+
return client.get(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/subscription/users/${userId}/${active ? "active" : "past"}`).then(({ data }) => data);
|
|
472
|
+
};
|
|
473
|
+
//#endregion
|
|
474
|
+
//#region src/submitCancellationRequest.ts
|
|
475
|
+
const schema = z.object({
|
|
476
|
+
bookingRequestId: z.string().uuid(),
|
|
477
|
+
userId: z.string().uuid()
|
|
478
|
+
});
|
|
479
|
+
const submitCancellationRequest = async (client, bookingRequestId, userId) => {
|
|
480
|
+
const result = schema.safeParse({
|
|
481
|
+
bookingRequestId,
|
|
482
|
+
userId
|
|
483
|
+
});
|
|
484
|
+
if (!result.success) throw new TypeError("Invalid args", { cause: result.error.issues });
|
|
485
|
+
return client.post(`/boapi/proxy/user/fleets/${client.clientOptions.fleetId}/bookingrequests/${bookingRequestId}/actions`, {
|
|
486
|
+
action: "EARLIER_CANCELLATION_REQUEST",
|
|
487
|
+
bookingStatusBO: "ONGOING",
|
|
488
|
+
status: "PENDING",
|
|
489
|
+
userId
|
|
490
|
+
}).then(({ data }) => data).catch((error) => {
|
|
491
|
+
throw new TypeError("Failed to submit cancellation request", { cause: error });
|
|
492
|
+
});
|
|
493
|
+
};
|
|
494
|
+
//#endregion
|
|
425
495
|
//#region src/createSubscription.ts
|
|
426
496
|
const createSubscriptionBodySchema = z.object({
|
|
427
497
|
userId: z.string().trim().min(1).uuid(),
|
|
@@ -451,4 +521,4 @@ const createSubscription = async (client, body) => {
|
|
|
451
521
|
return client.post(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/subscription/bookingrequests`, result.data).then(({ data }) => data);
|
|
452
522
|
};
|
|
453
523
|
//#endregion
|
|
454
|
-
export { allocateVehicle, cancelBookingRequest, createSubscription, deallocateVehicle, getAvailableVehicles, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getBookingRequestsByUserId, getSATBookingRequests, getScheduleBookingRequests, getStationById, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, releaseBRPayment, triggerBRPayment, updateScheduleBooking };
|
|
524
|
+
export { allocateVehicle, cancelBookingRequest, createSubscription, deallocateVehicle, getAdditionalDrivers, getAvailableVehicles, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getBookingRequestsByUserId, getDigitalContracts, getSATBookingRequests, getScheduleBookingRequests, getScheduledBookingById, getSlaves, getStationById, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, getSubscriptionsByUserId, releaseBRPayment, submitCancellationRequest, triggerBRPayment, updateScheduleBooking };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vulog/aima-booking",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.35",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.cts",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"author": "Vulog",
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@vulog/aima-client": "1.2.
|
|
36
|
-
"@vulog/aima-core": "1.2.
|
|
35
|
+
"@vulog/aima-client": "1.2.35",
|
|
36
|
+
"@vulog/aima-core": "1.2.35"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"es-toolkit": "^1.39.9",
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { describe, test, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { Client } from '@vulog/aima-client';
|
|
3
|
+
import { randomUUID } from 'crypto';
|
|
4
|
+
import { getAdditionalDrivers } from './getAdditionalDrivers';
|
|
5
|
+
|
|
6
|
+
describe('getAdditionalDrivers', () => {
|
|
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('throws Invalid parentId when parentId is empty', async () => {
|
|
20
|
+
await expect(getAdditionalDrivers(client, '')).rejects.toThrow(TypeError);
|
|
21
|
+
await expect(getAdditionalDrivers(client, '')).rejects.toMatchObject({
|
|
22
|
+
message: 'Invalid parentId',
|
|
23
|
+
});
|
|
24
|
+
expect(getMock).not.toHaveBeenCalled();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('calls GET with correct URL and returns additional drivers', async () => {
|
|
28
|
+
const parentId = randomUUID();
|
|
29
|
+
const drivers = [
|
|
30
|
+
{
|
|
31
|
+
id: randomUUID(),
|
|
32
|
+
fleetId: 'FLEET_ID',
|
|
33
|
+
bookingRequestId: parentId,
|
|
34
|
+
profileId: randomUUID(),
|
|
35
|
+
updateDate: '2025-01-15T10:00:00Z',
|
|
36
|
+
invitationEmail: 'driver@example.com',
|
|
37
|
+
profileStatus: 'APPROVED',
|
|
38
|
+
userId: randomUUID(),
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
getMock.mockResolvedValueOnce({ data: drivers });
|
|
42
|
+
|
|
43
|
+
const result = await getAdditionalDrivers(client, parentId);
|
|
44
|
+
|
|
45
|
+
expect(getMock).toHaveBeenCalledTimes(1);
|
|
46
|
+
expect(getMock).toHaveBeenCalledWith(
|
|
47
|
+
`/boapi/proxy/user/fleets/FLEET_ID/bookingrequests/${parentId}/additionalDrivers`
|
|
48
|
+
);
|
|
49
|
+
expect(result).toEqual(drivers);
|
|
50
|
+
expect(result).toHaveLength(1);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('returns empty array when no additional drivers', async () => {
|
|
54
|
+
const parentId = randomUUID();
|
|
55
|
+
getMock.mockResolvedValueOnce({ data: [] });
|
|
56
|
+
|
|
57
|
+
const result = await getAdditionalDrivers(client, parentId);
|
|
58
|
+
|
|
59
|
+
expect(result).toEqual([]);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Client } from '@vulog/aima-client';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
import { type AdditionalDriver } from './types';
|
|
5
|
+
|
|
6
|
+
const schema = z.object({
|
|
7
|
+
parentId: z.string().trim().min(1),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const getAdditionalDrivers = async (client: Client, parentId: string): Promise<AdditionalDriver[]> => {
|
|
11
|
+
const result = schema.safeParse({ parentId });
|
|
12
|
+
if (!result.success) {
|
|
13
|
+
throw new TypeError('Invalid parentId', {
|
|
14
|
+
cause: result.error.issues,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return client
|
|
19
|
+
.get<
|
|
20
|
+
AdditionalDriver[]
|
|
21
|
+
>(`/boapi/proxy/user/fleets/${client.clientOptions.fleetId}/bookingrequests/${parentId}/additionalDrivers`)
|
|
22
|
+
.then(({ data }) => data);
|
|
23
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { describe, test, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { Client } from '@vulog/aima-client';
|
|
3
|
+
import { getAvailableVehicles } from './getAvailableVehicles';
|
|
4
|
+
|
|
5
|
+
describe('getAvailableVehicles', () => {
|
|
6
|
+
const getMock = vi.fn();
|
|
7
|
+
const client = {
|
|
8
|
+
get: getMock,
|
|
9
|
+
clientOptions: {
|
|
10
|
+
fleetId: 'FLEET_ID',
|
|
11
|
+
},
|
|
12
|
+
} as unknown as Client;
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
getMock.mockReset();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('throws Invalid args when stationId is empty', async () => {
|
|
19
|
+
await expect(
|
|
20
|
+
getAvailableVehicles(client, '', '2025-02-10T12:00:00Z')
|
|
21
|
+
).rejects.toThrow(TypeError);
|
|
22
|
+
await expect(
|
|
23
|
+
getAvailableVehicles(client, '', '2025-02-10T12:00:00Z')
|
|
24
|
+
).rejects.toMatchObject({ message: 'Invalid args' });
|
|
25
|
+
expect(getMock).not.toHaveBeenCalled();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('throws Invalid args when startDate is invalid datetime', async () => {
|
|
29
|
+
await expect(
|
|
30
|
+
getAvailableVehicles(client, 'station-123', 'not-a-date')
|
|
31
|
+
).rejects.toThrow(TypeError);
|
|
32
|
+
expect(getMock).not.toHaveBeenCalled();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('calls GET with correct URL and returns available vehicles response', async () => {
|
|
36
|
+
const stationId = 'ded03b86-fa3f-4d79-80fa-191b2ec13b5e';
|
|
37
|
+
const startDate = '2025-02-10T12:00:00Z';
|
|
38
|
+
const response = {
|
|
39
|
+
stationId,
|
|
40
|
+
vehicles: [{ vehicleId: 'vehicle-1' }, { vehicleId: 'vehicle-2' }],
|
|
41
|
+
};
|
|
42
|
+
getMock.mockResolvedValueOnce({ data: response });
|
|
43
|
+
|
|
44
|
+
const result = await getAvailableVehicles(client, stationId, startDate);
|
|
45
|
+
|
|
46
|
+
expect(getMock).toHaveBeenCalledTimes(1);
|
|
47
|
+
expect(getMock).toHaveBeenCalledWith(
|
|
48
|
+
`/boapi/proxy/user/scheduledBooking/fleets/FLEET_ID/subscription/stations/${stationId}/vehicles/available?startDate=${startDate}`
|
|
49
|
+
);
|
|
50
|
+
expect(result).toEqual(response);
|
|
51
|
+
expect(result.vehicles).toHaveLength(2);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
getBookingRequestById,
|
|
4
|
+
getBookingRequestByTrip,
|
|
5
|
+
getSubscriptionBookingRequestById,
|
|
6
|
+
getScheduledBookingById,
|
|
7
|
+
} from './getBookingRequest';
|
|
3
8
|
import { Client } from '@vulog/aima-client';
|
|
4
9
|
import { randomUUID } from 'crypto';
|
|
5
10
|
import { PaymentReceipts } from './types';
|
|
@@ -436,3 +441,69 @@ describe('getsubscriptionBookingRequestByID', () => {
|
|
|
436
441
|
expect(result.station).toEqual(data.stationId);
|
|
437
442
|
});
|
|
438
443
|
});
|
|
444
|
+
|
|
445
|
+
describe('getScheduledBookingById', () => {
|
|
446
|
+
const getMock = vi.fn();
|
|
447
|
+
const client = {
|
|
448
|
+
get: getMock,
|
|
449
|
+
clientOptions: {
|
|
450
|
+
fleetId: 'FLEET_ID',
|
|
451
|
+
},
|
|
452
|
+
} as unknown as Client;
|
|
453
|
+
|
|
454
|
+
beforeEach(() => {
|
|
455
|
+
getMock.mockReset();
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
test('throws Invalid bookingId when bookingId is not a valid UUID', async () => {
|
|
459
|
+
await expect(getScheduledBookingById(client, 'not-a-uuid')).rejects.toThrow(TypeError);
|
|
460
|
+
await expect(getScheduledBookingById(client, 'not-a-uuid')).rejects.toMatchObject({
|
|
461
|
+
message: 'Invalid bookingId',
|
|
462
|
+
});
|
|
463
|
+
expect(getMock).not.toHaveBeenCalled();
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
test('throws Invalid bookingId when bookingId is empty', async () => {
|
|
467
|
+
await expect(getScheduledBookingById(client, '')).rejects.toThrow(TypeError);
|
|
468
|
+
expect(getMock).not.toHaveBeenCalled();
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
test('calls GET with by-service URL and returns SATBookingRequest', async () => {
|
|
472
|
+
const bookingId = randomUUID();
|
|
473
|
+
const data = {
|
|
474
|
+
id: bookingId,
|
|
475
|
+
startDate: '2026-03-03T10:00:00Z',
|
|
476
|
+
endDate: '2026-06-03T09:00:00Z',
|
|
477
|
+
returnedDate: null,
|
|
478
|
+
profileId: '76175b0c-7e39-41ad-a338-914df3a5fdf6',
|
|
479
|
+
vehicleId: null,
|
|
480
|
+
modelId: null,
|
|
481
|
+
journeyId: 'BEBD00056A9A16103D418CC36D940E26',
|
|
482
|
+
station: 'ded03b86-fa3f-4d79-80fa-191b2ec13b5e',
|
|
483
|
+
status: 'CONFIRMED',
|
|
484
|
+
creationDate: '2026-03-03T09:29:45Z',
|
|
485
|
+
fleetId: 'FLEET_ID',
|
|
486
|
+
userId: '20fb98a3-b60d-491a-9359-62e55f51fcb9',
|
|
487
|
+
serviceId: 'f49080b0-66bc-45e9-8e84-0dfb57bb8f92',
|
|
488
|
+
productIds: [],
|
|
489
|
+
pricingDetails: [],
|
|
490
|
+
completed: true,
|
|
491
|
+
rollingContract: true,
|
|
492
|
+
planDurationInMonths: 3,
|
|
493
|
+
planName: '3 mois',
|
|
494
|
+
contractType: 'SVS',
|
|
495
|
+
bookingReferenceId: 'q93UCF',
|
|
496
|
+
};
|
|
497
|
+
getMock.mockResolvedValueOnce({ data });
|
|
498
|
+
|
|
499
|
+
const result = await getScheduledBookingById(client, bookingId);
|
|
500
|
+
|
|
501
|
+
expect(getMock).toHaveBeenCalledTimes(1);
|
|
502
|
+
expect(getMock).toHaveBeenCalledWith(
|
|
503
|
+
`/boapi/proxy/user/scheduledBooking/by-service/fleets/FLEET_ID/bookingrequests/${bookingId}`
|
|
504
|
+
);
|
|
505
|
+
expect(result).toEqual(data);
|
|
506
|
+
expect(result.id).toBe(bookingId);
|
|
507
|
+
expect(result.status).toBe('CONFIRMED');
|
|
508
|
+
});
|
|
509
|
+
});
|
package/src/getBookingRequest.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Client } from '@vulog/aima-client';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
|
-
import { BookingRequest } from './types';
|
|
4
|
+
import { BookingRequest, SATBookingRequest } from './types';
|
|
5
5
|
|
|
6
6
|
export const getBookingRequestById = async (client: Client, id: string): Promise<BookingRequest> => {
|
|
7
7
|
const result = z.string().trim().min(1).uuid().safeParse(id);
|
|
@@ -46,3 +46,17 @@ export const getSubscriptionBookingRequestById = async (client: Client, id: stri
|
|
|
46
46
|
)
|
|
47
47
|
.then(({ data: { stationId, ...data } }) => ({ station: stationId, ...data }) as BookingRequest);
|
|
48
48
|
};
|
|
49
|
+
|
|
50
|
+
export const getScheduledBookingById = async (client: Client, bookingId: string): Promise<SATBookingRequest> => {
|
|
51
|
+
const result = z.string().trim().min(1).uuid().safeParse(bookingId);
|
|
52
|
+
if (!result.success) {
|
|
53
|
+
throw new TypeError('Invalid bookingId', {
|
|
54
|
+
cause: result.error.issues,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return client
|
|
58
|
+
.get<SATBookingRequest>(
|
|
59
|
+
`/boapi/proxy/user/scheduledBooking/by-service/fleets/${client.clientOptions.fleetId}/bookingrequests/${bookingId}`
|
|
60
|
+
)
|
|
61
|
+
.then(({ data }) => data);
|
|
62
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { describe, test, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { Client } from '@vulog/aima-client';
|
|
3
|
+
import { getDigitalContracts } from './getDigitalContracts';
|
|
4
|
+
import type { Contract } from './types';
|
|
5
|
+
|
|
6
|
+
describe('getDigitalContracts', () => {
|
|
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
|
+
const mockContracts: Contract[] = [
|
|
16
|
+
{
|
|
17
|
+
id: 'contract-1',
|
|
18
|
+
status: 'SIGNED',
|
|
19
|
+
provider: 'DOCUSIGN',
|
|
20
|
+
creationDate: '2026-03-03T10:00:00Z',
|
|
21
|
+
profileId: '76175b0c-7e39-41ad-a338-914df3a5fdf6',
|
|
22
|
+
externalContractId: 'ext-1',
|
|
23
|
+
type: 'RENTAL',
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
getMock.mockReset();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('throws Invalid args when bookingId is empty', async () => {
|
|
32
|
+
await expect(getDigitalContracts(client, '')).rejects.toThrow(TypeError);
|
|
33
|
+
await expect(getDigitalContracts(client, '')).rejects.toMatchObject({
|
|
34
|
+
message: 'Invalid args',
|
|
35
|
+
});
|
|
36
|
+
expect(getMock).not.toHaveBeenCalled();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('calls GET with default status SIGNED and returns contracts', async () => {
|
|
40
|
+
const bookingId = '66bcbd77-37ef-47bd-b9af-877e5d213b8f';
|
|
41
|
+
getMock.mockResolvedValueOnce({ data: mockContracts });
|
|
42
|
+
|
|
43
|
+
const result = await getDigitalContracts(client, bookingId);
|
|
44
|
+
|
|
45
|
+
expect(getMock).toHaveBeenCalledTimes(1);
|
|
46
|
+
expect(getMock).toHaveBeenCalledWith(
|
|
47
|
+
`/boapi/proxy/user/scheduledBooking/fleets/FLEET_ID/subscription/bookingrequests/${bookingId}/digitalContracts?status=SIGNED`
|
|
48
|
+
);
|
|
49
|
+
expect(result).toEqual(mockContracts);
|
|
50
|
+
expect(result[0].status).toBe('SIGNED');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('calls GET with custom status when provided', async () => {
|
|
54
|
+
const bookingId = '66bcbd77-37ef-47bd-b9af-877e5d213b8f';
|
|
55
|
+
getMock.mockResolvedValueOnce({ data: [] });
|
|
56
|
+
|
|
57
|
+
await getDigitalContracts(client, bookingId, 'PENDING');
|
|
58
|
+
|
|
59
|
+
expect(getMock).toHaveBeenCalledWith(
|
|
60
|
+
`/boapi/proxy/user/scheduledBooking/fleets/FLEET_ID/subscription/bookingrequests/${bookingId}/digitalContracts?status=PENDING`
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('returns empty array when no contracts', async () => {
|
|
65
|
+
const bookingId = 'some-booking-id';
|
|
66
|
+
getMock.mockResolvedValueOnce({ data: [] });
|
|
67
|
+
|
|
68
|
+
const result = await getDigitalContracts(client, bookingId);
|
|
69
|
+
|
|
70
|
+
expect(result).toEqual([]);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Client } from '@vulog/aima-client';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
import { Contract } from './types';
|
|
5
|
+
|
|
6
|
+
const schema = z.object({
|
|
7
|
+
bookingId: z.string().trim().min(1),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const getDigitalContracts = async (
|
|
11
|
+
client: Client,
|
|
12
|
+
bookingId: string,
|
|
13
|
+
status = 'SIGNED'
|
|
14
|
+
): Promise<Contract[]> => {
|
|
15
|
+
const result = schema.safeParse({ bookingId });
|
|
16
|
+
if (!result.success) {
|
|
17
|
+
throw new TypeError('Invalid args', {
|
|
18
|
+
cause: result.error.issues,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return client
|
|
22
|
+
.get<
|
|
23
|
+
Contract[]
|
|
24
|
+
>(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/subscription/bookingrequests/${result.data.bookingId}/digitalContracts?status=${encodeURIComponent(status)}`)
|
|
25
|
+
.then(({ data }) => data);
|
|
26
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { describe, test, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { Client } from '@vulog/aima-client';
|
|
3
|
+
import { randomUUID } from 'crypto';
|
|
4
|
+
import { getSlaves } from './getSlaves';
|
|
5
|
+
import type { BookingRequestSlave } from './types';
|
|
6
|
+
|
|
7
|
+
describe('getSlaves', () => {
|
|
8
|
+
const getMock = vi.fn();
|
|
9
|
+
const client = {
|
|
10
|
+
get: getMock,
|
|
11
|
+
clientOptions: {
|
|
12
|
+
fleetId: 'FLEET_ID',
|
|
13
|
+
},
|
|
14
|
+
} as unknown as Client;
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
getMock.mockReset();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('throws Invalid bookingId when parentId is empty', async () => {
|
|
21
|
+
await expect(getSlaves(client, '', 'UPCOMING')).rejects.toThrow(TypeError);
|
|
22
|
+
await expect(getSlaves(client, '', 'UPCOMING')).rejects.toMatchObject({
|
|
23
|
+
message: 'Invalid bookingId',
|
|
24
|
+
});
|
|
25
|
+
expect(getMock).not.toHaveBeenCalled();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('throws when status is not in enum', async () => {
|
|
29
|
+
const parentId = randomUUID();
|
|
30
|
+
await expect(getSlaves(client, parentId, 'INVALID_STATUS')).rejects.toThrow(TypeError);
|
|
31
|
+
expect(getMock).not.toHaveBeenCalled();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('calls GET with correct URL for UPCOMING and returns slaves', async () => {
|
|
35
|
+
const parentId = randomUUID();
|
|
36
|
+
const slaves: BookingRequestSlave[] = [
|
|
37
|
+
{
|
|
38
|
+
id: randomUUID(),
|
|
39
|
+
vehicleId: randomUUID(),
|
|
40
|
+
modelId: 2597,
|
|
41
|
+
startDate: '2026-03-03T10:00:00Z',
|
|
42
|
+
endDate: '2026-03-06T09:00:00Z',
|
|
43
|
+
tripId: 'BEBD00056A9A16103D418CC36D940E26',
|
|
44
|
+
parentId,
|
|
45
|
+
traveledDistance: 120,
|
|
46
|
+
energyLevelEnd: 80,
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
getMock.mockResolvedValueOnce({ data: slaves });
|
|
50
|
+
|
|
51
|
+
const result = await getSlaves(client, parentId, 'UPCOMING');
|
|
52
|
+
|
|
53
|
+
expect(getMock).toHaveBeenCalledTimes(1);
|
|
54
|
+
expect(getMock).toHaveBeenCalledWith(
|
|
55
|
+
`/boapi/proxy/user/scheduledBooking/fleets/FLEET_ID/subscription/bookingRequests/${parentId}/bookingRequestsSlave?bookingStatus=UPCOMING`
|
|
56
|
+
);
|
|
57
|
+
expect(result).toEqual(slaves);
|
|
58
|
+
expect(result).toHaveLength(1);
|
|
59
|
+
});
|
|
60
|
+
});
|
package/src/getSlaves.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Client } from '@vulog/aima-client';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
import { BookingRequestSlave } from './types';
|
|
5
|
+
|
|
6
|
+
const schema = z.object({
|
|
7
|
+
parentId: z.string().trim().min(1),
|
|
8
|
+
status: z.enum(['ONGOING, COMPLETED', 'UPCOMING']),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export const getSlaves = async (client: Client, parentId: string, status: string): Promise<BookingRequestSlave[]> => {
|
|
12
|
+
const result = schema.safeParse({ parentId, status });
|
|
13
|
+
if (!result.success) {
|
|
14
|
+
throw new TypeError('Invalid bookingId', {
|
|
15
|
+
cause: result.error.issues,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return client
|
|
20
|
+
.get<
|
|
21
|
+
BookingRequestSlave[]
|
|
22
|
+
>(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/subscription/bookingRequests/${parentId}/bookingRequestsSlave?bookingStatus=${status}`)
|
|
23
|
+
.then(({ data }) => data);
|
|
24
|
+
};
|