@vulog/aima-business 1.2.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/index.cjs +668 -0
  2. package/dist/index.d.cts +346 -0
  3. package/dist/index.d.mts +346 -0
  4. package/dist/index.mjs +609 -0
  5. package/package.json +42 -0
  6. package/src/addBusinessCredit.ts +31 -0
  7. package/src/addStripePayment.ts +18 -0
  8. package/src/addTripNote.test.ts +67 -0
  9. package/src/addTripNote.ts +30 -0
  10. package/src/addUserToBusiness.test.ts +74 -0
  11. package/src/addUserToBusiness.ts +49 -0
  12. package/src/archiveBusinessProfile.ts +28 -0
  13. package/src/bulkAddBusinessUsers.ts +27 -0
  14. package/src/businessDelegatedAdmin.test.ts +68 -0
  15. package/src/businessDelegatedAdmin.ts +32 -0
  16. package/src/businessOwner.test.ts +68 -0
  17. package/src/businessOwner.ts +32 -0
  18. package/src/chargeBusinessProduct.ts +31 -0
  19. package/src/createBusiness.test.ts +54 -0
  20. package/src/createBusiness.ts +23 -0
  21. package/src/createBusinessCostCenter.test.ts +61 -0
  22. package/src/createBusinessCostCenter.ts +34 -0
  23. package/src/deactivateBusinessProfile.ts +22 -0
  24. package/src/deleteBusinessCostCenter.test.ts +45 -0
  25. package/src/deleteBusinessCostCenter.ts +23 -0
  26. package/src/deleteInvitationRequest.test.ts +45 -0
  27. package/src/deleteInvitationRequest.ts +13 -0
  28. package/src/getBillingGroups.ts +9 -0
  29. package/src/getBusinessById.test.ts +47 -0
  30. package/src/getBusinessById.ts +15 -0
  31. package/src/getBusinessContacts.ts +17 -0
  32. package/src/getBusinessCostCenterById.ts +27 -0
  33. package/src/getBusinessCostCenters.ts +18 -0
  34. package/src/getBusinessInviteLink.ts +17 -0
  35. package/src/getBusinessInvoiceProducts.ts +24 -0
  36. package/src/getBusinessInvoiceTrips.ts +20 -0
  37. package/src/getBusinessInvoices.test.ts +92 -0
  38. package/src/getBusinessInvoices.ts +43 -0
  39. package/src/getBusinessPaymentDetails.ts +20 -0
  40. package/src/getBusinessProducts.ts +9 -0
  41. package/src/getBusinessTripById.ts +15 -0
  42. package/src/getBusinessUserById.ts +26 -0
  43. package/src/getBusinessUserGlobalById.ts +15 -0
  44. package/src/getBusinessUsers.test.ts +70 -0
  45. package/src/getBusinessUsers.ts +43 -0
  46. package/src/getBusinessWallet.test.ts +46 -0
  47. package/src/getBusinessWallet.ts +17 -0
  48. package/src/getBusinesses.test.ts +133 -0
  49. package/src/getBusinesses.ts +36 -0
  50. package/src/getEntityBalance.ts +17 -0
  51. package/src/getEntityProducts.ts +15 -0
  52. package/src/getEntityTrips.ts +13 -0
  53. package/src/getEntityTripsCost.ts +17 -0
  54. package/src/getInvitationRequest.test.ts +46 -0
  55. package/src/getInvitationRequest.ts +17 -0
  56. package/src/getInvoicePdf.test.ts +62 -0
  57. package/src/getInvoicePdf.ts +16 -0
  58. package/src/getInvoiceRefundNote.ts +17 -0
  59. package/src/getInvoiceRefundableAmount.ts +20 -0
  60. package/src/getOngoingTripNotes.ts +17 -0
  61. package/src/getOngoingTrips.test.ts +43 -0
  62. package/src/getOngoingTrips.ts +9 -0
  63. package/src/getStripePublishableKey.ts +9 -0
  64. package/src/getStripeSetup.ts +17 -0
  65. package/src/index.ts +58 -0
  66. package/src/inviteBusinessUser.ts +31 -0
  67. package/src/listBusinessUsersGlobal.test.ts +65 -0
  68. package/src/listBusinessUsersGlobal.ts +26 -0
  69. package/src/redeemBusinessPromoCode.ts +18 -0
  70. package/src/refundInvoice.test.ts +72 -0
  71. package/src/refundInvoice.ts +33 -0
  72. package/src/refundInvoiceAmount.ts +20 -0
  73. package/src/searchBusinessUsersByName.ts +27 -0
  74. package/src/searchBusinessUsersGlobal.ts +18 -0
  75. package/src/sendBusinessIban.ts +29 -0
  76. package/src/setInvoiceExternalPayment.ts +33 -0
  77. package/src/types.ts +163 -0
  78. package/src/updateBusiness.test.ts +65 -0
  79. package/src/updateBusiness.ts +35 -0
  80. package/src/updateBusinessCostCenter.ts +41 -0
  81. package/src/updateBusinessProfileStatus.ts +22 -0
  82. package/src/updateBusinessUserProfile.ts +51 -0
  83. package/src/updateInvoiceStatus.test.ts +54 -0
  84. package/src/updateInvoiceStatus.ts +19 -0
  85. package/tsconfig.json +9 -0
  86. package/tsdown.config.ts +8 -0
  87. package/vitest.config.ts +1 -0
@@ -0,0 +1,15 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ import { BusinessUser } from './types';
5
+
6
+ export const getBusinessUserGlobalById = async (client: Client, userId: string): Promise<BusinessUser> => {
7
+ const result = z.string().trim().min(1).uuid().safeParse(userId);
8
+ if (!result.success) {
9
+ throw new TypeError('Invalid args', { cause: result.error.issues });
10
+ }
11
+
12
+ return client
13
+ .get<BusinessUser>(`/boapi/proxy/business/fleets/${client.clientOptions.fleetId}/users/${result.data}`)
14
+ .then(({ data }) => data);
15
+ };
@@ -0,0 +1,70 @@
1
+ import { describe, test, vi, expect, beforeEach } from 'vitest';
2
+ import { Client } from '@vulog/aima-client';
3
+ import { getBusinessUsers } from './getBusinessUsers';
4
+
5
+ describe('getBusinessUsers', () => {
6
+ const getMock = vi.fn();
7
+ const client = {
8
+ get: getMock,
9
+ clientOptions: { fleetId: 'FLEET_ID' },
10
+ } as unknown as Client;
11
+
12
+ const businessId = 'ed539d7d-d815-405b-bc00-71008fb1954c';
13
+
14
+ beforeEach(() => {
15
+ vi.clearAllMocks();
16
+ });
17
+
18
+ test('should call GET with correct endpoint and default pagination', async () => {
19
+ const mockUsers = [
20
+ { userId: 'u1', businessId, role: 'MEMBER' },
21
+ { userId: 'u2', businessId, role: 'ADMIN' },
22
+ ];
23
+ getMock.mockResolvedValueOnce({
24
+ data: mockUsers,
25
+ headers: { number: 0, size: 100, totalelements: 2, totalpages: 1 },
26
+ });
27
+
28
+ const result = await getBusinessUsers(client, businessId);
29
+
30
+ expect(getMock).toHaveBeenCalledTimes(1);
31
+ const url = getMock.mock.calls[0][0] as string;
32
+ expect(url).toContain(`/boapi/proxy/business/fleets/FLEET_ID/business/${businessId}/user?`);
33
+ expect(url).toContain('page=0');
34
+ expect(url).toContain('size=100');
35
+ expect(result.data).toEqual(mockUsers);
36
+ expect(result.page).toBe(0);
37
+ expect(result.pageSize).toBe(100);
38
+ expect(result.total).toBe(2);
39
+ expect(result.totalPages).toBe(1);
40
+ });
41
+
42
+ test('should pass custom pagination options', async () => {
43
+ getMock.mockResolvedValueOnce({
44
+ data: [],
45
+ headers: { number: 2, size: 25, totalelements: 0, totalpages: 0 },
46
+ });
47
+
48
+ await getBusinessUsers(client, businessId, { page: 2, pageSize: 25, sort: 'userId', sortDirection: 'DESC' });
49
+
50
+ const url = getMock.mock.calls[0][0] as string;
51
+ expect(url).toContain('page=2');
52
+ expect(url).toContain('size=25');
53
+ expect(url).toContain('DESC');
54
+ });
55
+
56
+ test('should throw TypeError for invalid businessId', async () => {
57
+ await expect(getBusinessUsers(client, 'not-a-uuid')).rejects.toThrow(TypeError);
58
+ expect(getMock).not.toHaveBeenCalled();
59
+ });
60
+
61
+ test('should throw TypeError for empty businessId', async () => {
62
+ await expect(getBusinessUsers(client, '')).rejects.toThrow(TypeError);
63
+ expect(getMock).not.toHaveBeenCalled();
64
+ });
65
+
66
+ test('should throw TypeError for invalid pagination options', async () => {
67
+ await expect(getBusinessUsers(client, businessId, { page: -1 })).rejects.toThrow(TypeError);
68
+ expect(getMock).not.toHaveBeenCalled();
69
+ });
70
+ });
@@ -0,0 +1,43 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { createPaginableOptionsSchema, PaginableOptions, PaginableResponse } from '@vulog/aima-core';
3
+ import { z } from 'zod';
4
+
5
+ import { BusinessUser } from './types';
6
+
7
+ export const getBusinessUsers = async (
8
+ client: Client,
9
+ businessId: string,
10
+ options?: PaginableOptions
11
+ ): Promise<PaginableResponse<BusinessUser>> => {
12
+ const resultId = z.string().trim().min(1).uuid().safeParse(businessId);
13
+ if (!resultId.success) {
14
+ throw new TypeError('Invalid args', { cause: resultId.error.issues });
15
+ }
16
+
17
+ const paginableOptionsSchema = createPaginableOptionsSchema();
18
+
19
+ const resultOptions = paginableOptionsSchema.safeParse(options ?? {});
20
+ if (!resultOptions.success) {
21
+ throw new TypeError('Invalid options', { cause: resultOptions.error.issues });
22
+ }
23
+
24
+ const finalOptions = resultOptions.data;
25
+
26
+ const searchParams = new URLSearchParams();
27
+ searchParams.append('page', finalOptions.page!.toString());
28
+ searchParams.append('size', finalOptions.pageSize!.toString());
29
+
30
+ if (finalOptions.sort) {
31
+ searchParams.append('sort', `${finalOptions.sort.toString()},${finalOptions.sortDirection!.toString()}`);
32
+ }
33
+
34
+ const url = `/boapi/proxy/business/fleets/${client.clientOptions.fleetId}/business/${resultId.data}/user?${searchParams.toString()}`;
35
+
36
+ return client.get<BusinessUser[]>(url).then(({ data, headers }) => ({
37
+ data,
38
+ page: headers.number,
39
+ pageSize: headers.size,
40
+ total: headers.totalelements,
41
+ totalPages: headers.totalpages,
42
+ }));
43
+ };
@@ -0,0 +1,46 @@
1
+ import { describe, test, vi, expect, beforeEach } from 'vitest';
2
+ import { Client } from '@vulog/aima-client';
3
+ import { getBusinessWallet } from './getBusinessWallet';
4
+
5
+ describe('getBusinessWallet', () => {
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
+ vi.clearAllMocks();
16
+ });
17
+
18
+ const BUSINESS_ID = '018ab2b6-71b2-4c76-90bd-6e8d3f268618';
19
+
20
+ test('should return the business wallet', async () => {
21
+ const mockResponse = {
22
+ balance: 1000,
23
+ currency: 'EUR',
24
+ };
25
+ getMock.mockResolvedValueOnce({ data: mockResponse });
26
+
27
+ const result = await getBusinessWallet(client, BUSINESS_ID);
28
+
29
+ expect(result).toEqual(mockResponse);
30
+ expect(getMock).toHaveBeenCalledWith(
31
+ `/boapi/proxy/business/fleets/FLEET_ID/business/${BUSINESS_ID}/wallet`
32
+ );
33
+ });
34
+
35
+ test('should throw for empty businessId', async () => {
36
+ await expect(getBusinessWallet(client, '')).rejects.toThrow(TypeError);
37
+ });
38
+
39
+ test('should throw for non-uuid businessId', async () => {
40
+ await expect(getBusinessWallet(client, 'not-a-uuid')).rejects.toThrow(TypeError);
41
+ });
42
+
43
+ test('should throw for whitespace-only businessId', async () => {
44
+ await expect(getBusinessWallet(client, ' ')).rejects.toThrow(TypeError);
45
+ });
46
+ });
@@ -0,0 +1,17 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ import { BusinessWallet } from './types';
5
+
6
+ export const getBusinessWallet = async (client: Client, businessId: string): Promise<BusinessWallet> => {
7
+ const result = z.string().trim().min(1).uuid().safeParse(businessId);
8
+ if (!result.success) {
9
+ throw new TypeError('Invalid args', { cause: result.error.issues });
10
+ }
11
+
12
+ return client
13
+ .get<BusinessWallet>(
14
+ `/boapi/proxy/business/fleets/${client.clientOptions.fleetId}/business/${result.data}/wallet`
15
+ )
16
+ .then(({ data }) => data);
17
+ };
@@ -0,0 +1,133 @@
1
+ import { describe, test, vi, expect, beforeEach } from 'vitest';
2
+ import { Client } from '@vulog/aima-client';
3
+ import { getBusinesses } from './getBusinesses';
4
+ import { Business } from './types';
5
+
6
+ describe('getBusinesses', () => {
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
+ vi.clearAllMocks();
17
+ });
18
+
19
+ test('should return businesses with default options', async () => {
20
+ const mockData: Business[] = [
21
+ { id: 'id-1', name: 'Business One', status: 'ACTIVE' },
22
+ { id: 'id-2', name: 'Business Two', status: 'INACTIVE' },
23
+ ];
24
+
25
+ const mockHeaders = {
26
+ number: 0,
27
+ size: 100,
28
+ totalelements: 2,
29
+ totalpages: 1,
30
+ };
31
+
32
+ getMock.mockResolvedValueOnce({
33
+ data: mockData,
34
+ headers: mockHeaders,
35
+ });
36
+
37
+ const result = await getBusinesses(client);
38
+
39
+ expect(result).toEqual({
40
+ data: mockData,
41
+ page: 0,
42
+ pageSize: 100,
43
+ total: 2,
44
+ totalPages: 1,
45
+ });
46
+
47
+ expect(getMock).toHaveBeenCalledWith(
48
+ expect.stringContaining('/boapi/proxy/business/fleets/FLEET_ID/business')
49
+ );
50
+
51
+ const calledUrl = getMock.mock.calls[0][0];
52
+ const url = new URL(calledUrl, 'http://example.com');
53
+ expect(url.searchParams.get('page')).toBe('0');
54
+ expect(url.searchParams.get('size')).toBe('100');
55
+ });
56
+
57
+ test('should return businesses with custom options', async () => {
58
+ const mockData: Business[] = [
59
+ { id: 'id-1', name: 'Business One', status: 'ACTIVE' },
60
+ ];
61
+
62
+ const mockHeaders = {
63
+ number: 1,
64
+ size: 50,
65
+ totalelements: 10,
66
+ totalpages: 2,
67
+ };
68
+
69
+ getMock.mockResolvedValueOnce({
70
+ data: mockData,
71
+ headers: mockHeaders,
72
+ });
73
+
74
+ const options = {
75
+ page: 1,
76
+ pageSize: 50,
77
+ sort: 'name',
78
+ sortDirection: 'DESC' as const,
79
+ };
80
+
81
+ const result = await getBusinesses(client, options);
82
+
83
+ expect(result).toEqual({
84
+ data: mockData,
85
+ page: 1,
86
+ pageSize: 50,
87
+ total: 10,
88
+ totalPages: 2,
89
+ });
90
+
91
+ const calledUrl = getMock.mock.calls[0][0];
92
+ const url = new URL(calledUrl, 'http://example.com');
93
+ expect(url.searchParams.get('page')).toBe('1');
94
+ expect(url.searchParams.get('size')).toBe('50');
95
+ expect(url.searchParams.get('sort')).toBe('name,DESC');
96
+ });
97
+
98
+ test('should handle empty response', async () => {
99
+ const mockHeaders = {
100
+ number: 0,
101
+ size: 100,
102
+ totalelements: 0,
103
+ totalpages: 0,
104
+ };
105
+
106
+ getMock.mockResolvedValueOnce({
107
+ data: [],
108
+ headers: mockHeaders,
109
+ });
110
+
111
+ const result = await getBusinesses(client);
112
+
113
+ expect(result).toEqual({
114
+ data: [],
115
+ page: 0,
116
+ pageSize: 100,
117
+ total: 0,
118
+ totalPages: 0,
119
+ });
120
+ });
121
+
122
+ test('should throw error for invalid page number', async () => {
123
+ await expect(getBusinesses(client, { page: -1 })).rejects.toThrow('Invalid options');
124
+ });
125
+
126
+ test('should throw error for invalid page size', async () => {
127
+ await expect(getBusinesses(client, { pageSize: 0 })).rejects.toThrow('Invalid options');
128
+ });
129
+
130
+ test('should throw error for invalid sort direction', async () => {
131
+ await expect(getBusinesses(client, { sortDirection: 'INVALID' as any })).rejects.toThrow('Invalid options');
132
+ });
133
+ });
@@ -0,0 +1,36 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { createPaginableOptionsSchema, PaginableOptions, PaginableResponse } from '@vulog/aima-core';
3
+
4
+ import { Business } from './types';
5
+
6
+ export const getBusinesses = async (
7
+ client: Client,
8
+ options?: PaginableOptions
9
+ ): Promise<PaginableResponse<Business>> => {
10
+ const paginableOptionsSchema = createPaginableOptionsSchema();
11
+
12
+ const resultOptions = paginableOptionsSchema.safeParse(options ?? {});
13
+ if (!resultOptions.success) {
14
+ throw new TypeError('Invalid options', { cause: resultOptions.error.issues });
15
+ }
16
+
17
+ const finalOptions = resultOptions.data;
18
+
19
+ const searchParams = new URLSearchParams();
20
+ searchParams.append('page', finalOptions.page!.toString());
21
+ searchParams.append('size', finalOptions.pageSize!.toString());
22
+
23
+ if (finalOptions.sort) {
24
+ searchParams.append('sort', `${finalOptions.sort.toString()},${finalOptions.sortDirection!.toString()}`);
25
+ }
26
+
27
+ const url = `/boapi/proxy/business/fleets/${client.clientOptions.fleetId}/business?${searchParams.toString()}`;
28
+
29
+ return client.get<Business[]>(url).then(({ data, headers }) => ({
30
+ data,
31
+ page: headers.number,
32
+ pageSize: headers.size,
33
+ total: headers.totalelements,
34
+ totalPages: headers.totalpages,
35
+ }));
36
+ };
@@ -0,0 +1,17 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ import { EntityBalance } from './types';
5
+
6
+ export const getEntityBalance = async (client: Client, entityId: string): Promise<EntityBalance> => {
7
+ const result = z.string().trim().min(1).uuid().safeParse(entityId);
8
+ if (!result.success) {
9
+ throw new TypeError('Invalid args', { cause: result.error.issues });
10
+ }
11
+
12
+ return client
13
+ .get<EntityBalance>(
14
+ `/boapi/proxy/business/fleets/${client.clientOptions.fleetId}/billing/entity/${result.data}/balance`
15
+ )
16
+ .then(({ data }) => data);
17
+ };
@@ -0,0 +1,15 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ export const getEntityProducts = async (client: Client, entityId: string): Promise<any[]> => {
5
+ const result = z.string().trim().min(1).uuid().safeParse(entityId);
6
+ if (!result.success) {
7
+ throw new TypeError('Invalid args', { cause: result.error.issues });
8
+ }
9
+
10
+ return client
11
+ .get<
12
+ any[]
13
+ >(`/boapi/proxy/business/fleets/${client.clientOptions.fleetId}/billing/entity/${result.data}/product`)
14
+ .then(({ data }) => data);
15
+ };
@@ -0,0 +1,13 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ export const getEntityTrips = async (client: Client, entityId: string): Promise<any[]> => {
5
+ const result = z.string().trim().min(1).uuid().safeParse(entityId);
6
+ if (!result.success) {
7
+ throw new TypeError('Invalid args', { cause: result.error.issues });
8
+ }
9
+
10
+ return client
11
+ .get<any[]>(`/boapi/proxy/business/fleets/${client.clientOptions.fleetId}/billing/entity/${result.data}/trip`)
12
+ .then(({ data }) => data);
13
+ };
@@ -0,0 +1,17 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ import { EntityTripsCost } from './types';
5
+
6
+ export const getEntityTripsCost = async (client: Client, entityId: string): Promise<EntityTripsCost> => {
7
+ const result = z.string().trim().min(1).uuid().safeParse(entityId);
8
+ if (!result.success) {
9
+ throw new TypeError('Invalid args', { cause: result.error.issues });
10
+ }
11
+
12
+ return client
13
+ .get<EntityTripsCost>(
14
+ `/boapi/proxy/business/fleets/${client.clientOptions.fleetId}/billing/entity/${result.data}/trips/cost`
15
+ )
16
+ .then(({ data }) => data);
17
+ };
@@ -0,0 +1,46 @@
1
+ import { describe, test, vi, expect, beforeEach } from 'vitest';
2
+ import { Client } from '@vulog/aima-client';
3
+ import { getInvitationRequest } from './getInvitationRequest';
4
+
5
+ describe('getInvitationRequest', () => {
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
+ vi.clearAllMocks();
16
+ });
17
+
18
+ const INVITATION_ID = '018ab2b6-71b2-4c76-90bd-6e8d3f268618';
19
+
20
+ test('should return an invitation request by id', async () => {
21
+ const mockResponse = { id: INVITATION_ID, status: 'PENDING' };
22
+ getMock.mockResolvedValueOnce({ data: mockResponse });
23
+
24
+ const result = await getInvitationRequest(client, INVITATION_ID);
25
+
26
+ expect(result).toEqual(mockResponse);
27
+ expect(getMock).toHaveBeenCalledWith(
28
+ `/boapi/proxy/business/fleets/FLEET_ID/invitationRequest/${INVITATION_ID}`
29
+ );
30
+ });
31
+
32
+ test('should throw for empty invitationId', async () => {
33
+ await expect(getInvitationRequest(client, '')).rejects.toThrow(TypeError);
34
+ expect(getMock).not.toHaveBeenCalled();
35
+ });
36
+
37
+ test('should throw for non-uuid invitationId', async () => {
38
+ await expect(getInvitationRequest(client, 'not-a-uuid')).rejects.toThrow(TypeError);
39
+ expect(getMock).not.toHaveBeenCalled();
40
+ });
41
+
42
+ test('should throw for whitespace-only invitationId', async () => {
43
+ await expect(getInvitationRequest(client, ' ')).rejects.toThrow(TypeError);
44
+ expect(getMock).not.toHaveBeenCalled();
45
+ });
46
+ });
@@ -0,0 +1,17 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ import { InvitationRequest } from './types';
5
+
6
+ export const getInvitationRequest = async (client: Client, invitationId: string): Promise<InvitationRequest> => {
7
+ const result = z.string().trim().min(1).uuid().safeParse(invitationId);
8
+ if (!result.success) {
9
+ throw new TypeError('Invalid args', { cause: result.error.issues });
10
+ }
11
+
12
+ return client
13
+ .get<InvitationRequest>(
14
+ `/boapi/proxy/business/fleets/${client.clientOptions.fleetId}/invitationRequest/${result.data}`
15
+ )
16
+ .then(({ data }) => data);
17
+ };
@@ -0,0 +1,62 @@
1
+ import { describe, test, vi, expect, beforeEach } from 'vitest';
2
+ import { Client } from '@vulog/aima-client';
3
+ import { getInvoicePdf } from './getInvoicePdf';
4
+
5
+ describe('getInvoicePdf', () => {
6
+ const getMock = vi.fn();
7
+ const client = {
8
+ get: getMock,
9
+ clientOptions: { fleetId: 'FLEET_ID' },
10
+ } as unknown as Client;
11
+
12
+ const INVOICE_ID = '018ab2b6-71b2-4c76-90bd-6e8d3f268618';
13
+
14
+ beforeEach(() => {
15
+ vi.clearAllMocks();
16
+ });
17
+
18
+ test('should return ArrayBuffer when pdf has content', async () => {
19
+ const mockBuffer = new ArrayBuffer(1024);
20
+ getMock.mockResolvedValueOnce({ data: mockBuffer });
21
+
22
+ const result = await getInvoicePdf(client, INVOICE_ID);
23
+
24
+ expect(result).toBe(mockBuffer);
25
+ expect(getMock).toHaveBeenCalledWith(
26
+ `/boapi/proxy/business/fleets/FLEET_ID/invoices/${INVOICE_ID}/pdf`,
27
+ { responseType: 'arraybuffer' }
28
+ );
29
+ });
30
+
31
+ test('should return null when pdf is empty', async () => {
32
+ const emptyBuffer = new ArrayBuffer(0);
33
+ getMock.mockResolvedValueOnce({ data: emptyBuffer });
34
+
35
+ const result = await getInvoicePdf(client, INVOICE_ID);
36
+
37
+ expect(result).toBeNull();
38
+ });
39
+
40
+ test('should return null when data is null', async () => {
41
+ getMock.mockResolvedValueOnce({ data: null });
42
+
43
+ const result = await getInvoicePdf(client, INVOICE_ID);
44
+
45
+ expect(result).toBeNull();
46
+ });
47
+
48
+ test('should throw for empty invoiceId', async () => {
49
+ await expect(getInvoicePdf(client, '')).rejects.toThrow(TypeError);
50
+ expect(getMock).not.toHaveBeenCalled();
51
+ });
52
+
53
+ test('should throw for non-uuid invoiceId', async () => {
54
+ await expect(getInvoicePdf(client, 'not-a-uuid')).rejects.toThrow(TypeError);
55
+ expect(getMock).not.toHaveBeenCalled();
56
+ });
57
+
58
+ test('should throw for whitespace-only invoiceId', async () => {
59
+ await expect(getInvoicePdf(client, ' ')).rejects.toThrow(TypeError);
60
+ expect(getMock).not.toHaveBeenCalled();
61
+ });
62
+ });
@@ -0,0 +1,16 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ export const getInvoicePdf = async (client: Client, invoiceId: string): Promise<ArrayBuffer | null> => {
5
+ const result = z.string().trim().min(1).uuid().safeParse(invoiceId);
6
+ if (!result.success) {
7
+ throw new TypeError('Invalid args', { cause: result.error.issues });
8
+ }
9
+
10
+ const { data } = await client.get<ArrayBuffer>(
11
+ `/boapi/proxy/business/fleets/${client.clientOptions.fleetId}/invoices/${result.data}/pdf`,
12
+ { responseType: 'arraybuffer' }
13
+ );
14
+
15
+ return data && data.byteLength > 0 ? data : null;
16
+ };
@@ -0,0 +1,17 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ import { InvoiceRefundNote } from './types';
5
+
6
+ export const getInvoiceRefundNote = async (client: Client, invoiceId: string): Promise<InvoiceRefundNote> => {
7
+ const result = z.string().trim().min(1).uuid().safeParse(invoiceId);
8
+ if (!result.success) {
9
+ throw new TypeError('Invalid args', { cause: result.error.issues });
10
+ }
11
+
12
+ return client
13
+ .get<InvoiceRefundNote>(
14
+ `/boapi/proxy/business/fleets/${client.clientOptions.fleetId}/invoices/${result.data}/refundNote`
15
+ )
16
+ .then(({ data }) => data);
17
+ };
@@ -0,0 +1,20 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ import { InvoiceRefundableAmount } from './types';
5
+
6
+ export const getInvoiceRefundableAmount = async (
7
+ client: Client,
8
+ invoiceId: string
9
+ ): Promise<InvoiceRefundableAmount> => {
10
+ const result = z.string().trim().min(1).uuid().safeParse(invoiceId);
11
+ if (!result.success) {
12
+ throw new TypeError('Invalid args', { cause: result.error.issues });
13
+ }
14
+
15
+ return client
16
+ .get<InvoiceRefundableAmount>(
17
+ `/boapi/proxy/business/fleets/${client.clientOptions.fleetId}/invoices/${result.data}/refundableAmount`
18
+ )
19
+ .then(({ data }) => data);
20
+ };
@@ -0,0 +1,17 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ import { TripNote } from './types';
5
+
6
+ export const getOngoingTripNotes = async (client: Client, tripId: string): Promise<TripNote[]> => {
7
+ const result = z.string().trim().min(1).uuid().safeParse(tripId);
8
+ if (!result.success) {
9
+ throw new TypeError('Invalid args', { cause: result.error.issues });
10
+ }
11
+
12
+ return client
13
+ .get<
14
+ TripNote[]
15
+ >(`/boapi/proxy/business/fleets/${client.clientOptions.fleetId}/ongoingTrip/${result.data}/notes`)
16
+ .then(({ data }) => data);
17
+ };