@t4dhg/mcp-factorial 4.0.0 → 6.0.0
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 +1 -1
- package/dist/api.d.ts +8 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +213 -285
- package/dist/api.js.map +1 -1
- package/dist/endpoints.d.ts +51 -0
- package/dist/endpoints.d.ts.map +1 -0
- package/dist/endpoints.js +63 -0
- package/dist/endpoints.js.map +1 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +22 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.js +95 -253
- package/dist/index.js.map +1 -1
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js +2 -1
- package/dist/pagination.js.map +1 -1
- package/dist/schemas.d.ts +3 -3
- package/dist/schemas.js +1 -1
- package/dist/schemas.js.map +1 -1
- package/dist/tool-utils.d.ts +59 -0
- package/dist/tool-utils.d.ts.map +1 -0
- package/dist/tool-utils.js +71 -0
- package/dist/tool-utils.js.map +1 -0
- package/dist/utils.d.ts +33 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +48 -0
- package/dist/utils.js.map +1 -0
- package/package.json +1 -1
package/dist/api.js
CHANGED
|
@@ -5,8 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { fetchList, fetchOne, postOne, patchOne, deleteOne, postAction } from './http-client.js';
|
|
7
7
|
import { cache, cached, CACHE_TTL, CacheManager } from './cache.js';
|
|
8
|
+
import { debug } from './config.js';
|
|
8
9
|
import { buildPaginationParams, paginateResponse, sliceForPagination, } from './pagination.js';
|
|
9
10
|
import { AuditAction, auditedOperation } from './audit.js';
|
|
11
|
+
import { validateId } from './utils.js';
|
|
12
|
+
import { ENDPOINTS, endpointWithId, endpointWithAction } from './endpoints.js';
|
|
13
|
+
import { NotFoundError } from './errors.js';
|
|
10
14
|
// ============================================================================
|
|
11
15
|
// Employee endpoints
|
|
12
16
|
// ============================================================================
|
|
@@ -19,7 +23,7 @@ export async function listEmployees(options) {
|
|
|
19
23
|
// For filtered requests, we need to fetch all and filter client-side
|
|
20
24
|
// because the API doesn't reliably filter
|
|
21
25
|
if (options?.team_id || options?.location_id) {
|
|
22
|
-
const allEmployees = await cached('employees:all', () => fetchList(
|
|
26
|
+
const allEmployees = await cached('employees:all', () => fetchList(ENDPOINTS.employees), CACHE_TTL.employees);
|
|
23
27
|
let filtered = allEmployees;
|
|
24
28
|
if (options.team_id) {
|
|
25
29
|
filtered = filtered.filter(e => e.team_ids?.includes(options.team_id));
|
|
@@ -30,7 +34,7 @@ export async function listEmployees(options) {
|
|
|
30
34
|
return sliceForPagination(filtered, params);
|
|
31
35
|
}
|
|
32
36
|
// Without filters, use pagination directly
|
|
33
|
-
const employees = await cached(cacheKey, () => fetchList(
|
|
37
|
+
const employees = await cached(cacheKey, () => fetchList(ENDPOINTS.employees, { params }), CACHE_TTL.employees);
|
|
34
38
|
return paginateResponse(employees, params.page, params.limit);
|
|
35
39
|
}
|
|
36
40
|
/**
|
|
@@ -41,12 +45,10 @@ export async function listEmployees(options) {
|
|
|
41
45
|
* if the direct endpoint fails or returns no data.
|
|
42
46
|
*/
|
|
43
47
|
export async function getEmployee(id) {
|
|
44
|
-
|
|
45
|
-
throw new Error('Invalid employee ID. Please provide a positive number.');
|
|
46
|
-
}
|
|
48
|
+
validateId(id, 'employee');
|
|
47
49
|
// Try the direct endpoint first
|
|
48
50
|
try {
|
|
49
|
-
const employee = await cached(`employee:${id}`, () => fetchOne(
|
|
51
|
+
const employee = await cached(`employee:${id}`, () => fetchOne(endpointWithId(ENDPOINTS.employees, id)), CACHE_TTL.employees);
|
|
50
52
|
// If we got a valid employee, return it
|
|
51
53
|
if (employee) {
|
|
52
54
|
return employee;
|
|
@@ -55,13 +57,13 @@ export async function getEmployee(id) {
|
|
|
55
57
|
catch (error) {
|
|
56
58
|
// If direct fetch fails with NotFoundError, try fallback
|
|
57
59
|
// (other errors will be re-thrown below)
|
|
58
|
-
if (!(error instanceof
|
|
60
|
+
if (!(error instanceof NotFoundError)) {
|
|
59
61
|
throw error;
|
|
60
62
|
}
|
|
61
63
|
}
|
|
62
64
|
// Fallback: Fetch all employees and filter (same approach as searchEmployees)
|
|
63
65
|
// This works around Factorial API limitations with the individual employee endpoint
|
|
64
|
-
const allEmployees = await cached('employees:all', () => fetchList(
|
|
66
|
+
const allEmployees = await cached('employees:all', () => fetchList(ENDPOINTS.employees), CACHE_TTL.employees);
|
|
65
67
|
const employee = allEmployees.find(emp => emp.id === id);
|
|
66
68
|
if (!employee) {
|
|
67
69
|
throw new Error(`Employee with ID ${id} not found.`);
|
|
@@ -75,7 +77,7 @@ export async function searchEmployees(query) {
|
|
|
75
77
|
if (!query || query.trim().length < 2) {
|
|
76
78
|
throw new Error('Search query must be at least 2 characters long.');
|
|
77
79
|
}
|
|
78
|
-
const allEmployees = await cached('employees:all', () => fetchList(
|
|
80
|
+
const allEmployees = await cached('employees:all', () => fetchList(ENDPOINTS.employees), CACHE_TTL.employees);
|
|
79
81
|
const lowerQuery = query.toLowerCase().trim();
|
|
80
82
|
return allEmployees.filter(emp => emp.full_name?.toLowerCase().includes(lowerQuery) ||
|
|
81
83
|
emp.email?.toLowerCase().includes(lowerQuery) ||
|
|
@@ -91,17 +93,15 @@ export async function searchEmployees(query) {
|
|
|
91
93
|
export async function listTeams(options) {
|
|
92
94
|
const params = buildPaginationParams(options);
|
|
93
95
|
const cacheKey = CacheManager.key('teams', options);
|
|
94
|
-
const teams = await cached(cacheKey, () => fetchList(
|
|
96
|
+
const teams = await cached(cacheKey, () => fetchList(ENDPOINTS.teams), CACHE_TTL.teams);
|
|
95
97
|
return sliceForPagination(teams, params);
|
|
96
98
|
}
|
|
97
99
|
/**
|
|
98
100
|
* Get a specific team by ID
|
|
99
101
|
*/
|
|
100
102
|
export async function getTeam(id) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
return cached(`team:${id}`, () => fetchOne(`/teams/teams/${id}`), CACHE_TTL.teams);
|
|
103
|
+
validateId(id, 'team');
|
|
104
|
+
return cached(`team:${id}`, () => fetchOne(endpointWithId(ENDPOINTS.teams, id)), CACHE_TTL.teams);
|
|
105
105
|
}
|
|
106
106
|
// ============================================================================
|
|
107
107
|
// Location endpoints
|
|
@@ -112,17 +112,15 @@ export async function getTeam(id) {
|
|
|
112
112
|
export async function listLocations(options) {
|
|
113
113
|
const params = buildPaginationParams(options);
|
|
114
114
|
const cacheKey = CacheManager.key('locations', options);
|
|
115
|
-
const locations = await cached(cacheKey, () => fetchList(
|
|
115
|
+
const locations = await cached(cacheKey, () => fetchList(ENDPOINTS.locations), CACHE_TTL.locations);
|
|
116
116
|
return sliceForPagination(locations, params);
|
|
117
117
|
}
|
|
118
118
|
/**
|
|
119
119
|
* Get a specific location by ID
|
|
120
120
|
*/
|
|
121
121
|
export async function getLocation(id) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
return cached(`location:${id}`, () => fetchOne(`/locations/locations/${id}`), CACHE_TTL.locations);
|
|
122
|
+
validateId(id, 'location');
|
|
123
|
+
return cached(`location:${id}`, () => fetchOne(endpointWithId(ENDPOINTS.locations, id)), CACHE_TTL.locations);
|
|
126
124
|
}
|
|
127
125
|
// ============================================================================
|
|
128
126
|
// Contract endpoints
|
|
@@ -131,13 +129,13 @@ export async function getLocation(id) {
|
|
|
131
129
|
* List contracts, optionally filtered by employee ID
|
|
132
130
|
*/
|
|
133
131
|
export async function listContracts(employeeId, options) {
|
|
134
|
-
if (employeeId !== undefined
|
|
135
|
-
|
|
132
|
+
if (employeeId !== undefined) {
|
|
133
|
+
validateId(employeeId, 'employee');
|
|
136
134
|
}
|
|
137
135
|
const params = buildPaginationParams(options);
|
|
138
136
|
// Note: The API doesn't reliably filter by employee_id query param,
|
|
139
137
|
// so we fetch all contracts and filter client-side
|
|
140
|
-
const allContracts = await cached('contracts:all', () => fetchList(
|
|
138
|
+
const allContracts = await cached('contracts:all', () => fetchList(ENDPOINTS.contracts), CACHE_TTL.contracts);
|
|
141
139
|
const filtered = employeeId !== undefined
|
|
142
140
|
? allContracts.filter(c => c.employee_id === employeeId)
|
|
143
141
|
: allContracts;
|
|
@@ -163,32 +161,28 @@ export async function listLeaves(options) {
|
|
|
163
161
|
queryParams.start_on_gte = options.start_on_gte;
|
|
164
162
|
if (options?.start_on_lte)
|
|
165
163
|
queryParams.start_on_lte = options.start_on_lte;
|
|
166
|
-
const leaves = await fetchList(
|
|
164
|
+
const leaves = await fetchList(ENDPOINTS.leaves, { params: queryParams });
|
|
167
165
|
return paginateResponse(leaves, params.page, params.limit);
|
|
168
166
|
}
|
|
169
167
|
/**
|
|
170
168
|
* Get a specific leave by ID
|
|
171
169
|
*/
|
|
172
170
|
export async function getLeave(id) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
return fetchOne(`/timeoff/leaves/${id}`);
|
|
171
|
+
validateId(id, 'leave');
|
|
172
|
+
return fetchOne(endpointWithId(ENDPOINTS.leaves, id));
|
|
177
173
|
}
|
|
178
174
|
/**
|
|
179
175
|
* List all leave types
|
|
180
176
|
*/
|
|
181
177
|
export async function listLeaveTypes() {
|
|
182
|
-
return cached('leave-types:all', () => fetchList(
|
|
178
|
+
return cached('leave-types:all', () => fetchList(ENDPOINTS.leaveTypes), CACHE_TTL.leaves);
|
|
183
179
|
}
|
|
184
180
|
/**
|
|
185
181
|
* Get a specific leave type by ID
|
|
186
182
|
*/
|
|
187
183
|
export async function getLeaveType(id) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
return fetchOne(`/timeoff/leave-types/${id}`);
|
|
184
|
+
validateId(id, 'leave type');
|
|
185
|
+
return fetchOne(endpointWithId(ENDPOINTS.leaveTypes, id));
|
|
192
186
|
}
|
|
193
187
|
/**
|
|
194
188
|
* List allowances with optional filtering by employee
|
|
@@ -201,7 +195,7 @@ export async function listAllowances(options) {
|
|
|
201
195
|
};
|
|
202
196
|
if (options?.employee_id)
|
|
203
197
|
queryParams.employee_id = options.employee_id;
|
|
204
|
-
const allowances = await fetchList(
|
|
198
|
+
const allowances = await fetchList(ENDPOINTS.allowances, { params: queryParams });
|
|
205
199
|
return paginateResponse(allowances, params.page, params.limit);
|
|
206
200
|
}
|
|
207
201
|
// ============================================================================
|
|
@@ -222,17 +216,15 @@ export async function listShifts(options) {
|
|
|
222
216
|
queryParams.clock_in_gte = options.clock_in_gte;
|
|
223
217
|
if (options?.clock_in_lte)
|
|
224
218
|
queryParams.clock_in_lte = options.clock_in_lte;
|
|
225
|
-
const shifts = await fetchList(
|
|
219
|
+
const shifts = await fetchList(ENDPOINTS.shifts, { params: queryParams });
|
|
226
220
|
return paginateResponse(shifts, params.page, params.limit);
|
|
227
221
|
}
|
|
228
222
|
/**
|
|
229
223
|
* Get a specific shift by ID
|
|
230
224
|
*/
|
|
231
225
|
export async function getShift(id) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
return fetchOne(`/attendance/shifts/${id}`);
|
|
226
|
+
validateId(id, 'shift');
|
|
227
|
+
return fetchOne(endpointWithId(ENDPOINTS.shifts, id));
|
|
236
228
|
}
|
|
237
229
|
// ============================================================================
|
|
238
230
|
// Document endpoints (Read-only)
|
|
@@ -241,16 +233,14 @@ export async function getShift(id) {
|
|
|
241
233
|
* List all folders
|
|
242
234
|
*/
|
|
243
235
|
export async function listFolders() {
|
|
244
|
-
return cached('folders:all', () => fetchList(
|
|
236
|
+
return cached('folders:all', () => fetchList(ENDPOINTS.folders), CACHE_TTL.default);
|
|
245
237
|
}
|
|
246
238
|
/**
|
|
247
239
|
* Get a specific folder by ID
|
|
248
240
|
*/
|
|
249
241
|
export async function getFolder(id) {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
return fetchOne(`/documents/folders/${id}`);
|
|
242
|
+
validateId(id, 'folder');
|
|
243
|
+
return fetchOne(endpointWithId(ENDPOINTS.folders, id));
|
|
254
244
|
}
|
|
255
245
|
/**
|
|
256
246
|
* List documents with optional filtering by folder
|
|
@@ -271,20 +261,56 @@ export async function listDocuments(options) {
|
|
|
271
261
|
const baseParams = new URLSearchParams(queryParams).toString();
|
|
272
262
|
const fullParams = baseParams ? `${baseParams}&${employeeIdsParam}` : employeeIdsParam;
|
|
273
263
|
// Make request with custom query string
|
|
274
|
-
const documents = await fetchList(
|
|
264
|
+
const documents = await fetchList(`${ENDPOINTS.documents}?${fullParams}`);
|
|
265
|
+
debug(`listDocuments returned ${documents.length} documents`, {
|
|
266
|
+
sampleDocument: documents[0],
|
|
267
|
+
missingNames: documents.filter(d => !d.name).length,
|
|
268
|
+
});
|
|
275
269
|
return paginateResponse(documents, params.page, params.limit);
|
|
276
270
|
}
|
|
277
|
-
const documents = await fetchList(
|
|
271
|
+
const documents = await fetchList(ENDPOINTS.documents, { params: queryParams });
|
|
272
|
+
debug(`listDocuments returned ${documents.length} documents`, {
|
|
273
|
+
sampleDocument: documents[0],
|
|
274
|
+
missingNames: documents.filter(d => !d.name).length,
|
|
275
|
+
});
|
|
278
276
|
return paginateResponse(documents, params.page, params.limit);
|
|
279
277
|
}
|
|
280
278
|
/**
|
|
281
279
|
* Get a specific document by ID
|
|
280
|
+
*
|
|
281
|
+
* Note: The Factorial API's individual document endpoint (/documents/documents/{id})
|
|
282
|
+
* can be unreliable, similar to the employee endpoint. This function implements a fallback
|
|
283
|
+
* to listing all documents and filtering if the direct endpoint fails or returns no data.
|
|
284
|
+
*
|
|
285
|
+
* @param id - The document ID
|
|
286
|
+
* @returns The document object
|
|
287
|
+
* @throws Error if document is not found
|
|
282
288
|
*/
|
|
283
289
|
export async function getDocument(id) {
|
|
284
|
-
|
|
285
|
-
|
|
290
|
+
validateId(id, 'document');
|
|
291
|
+
// Try the direct endpoint first
|
|
292
|
+
try {
|
|
293
|
+
const document = await fetchOne(endpointWithId(ENDPOINTS.documents, id));
|
|
294
|
+
// If we got a valid document, return it
|
|
295
|
+
if (document) {
|
|
296
|
+
return document;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
// If direct fetch fails with NotFoundError, try fallback
|
|
301
|
+
if (!(error instanceof NotFoundError)) {
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
debug(`getDocument(${id}) - direct endpoint failed, using fallback`);
|
|
286
305
|
}
|
|
287
|
-
|
|
306
|
+
// Fallback: Fetch all documents and filter by ID
|
|
307
|
+
// This works around Factorial API limitations with the individual document endpoint
|
|
308
|
+
const allDocuments = await fetchList(ENDPOINTS.documents);
|
|
309
|
+
const document = allDocuments.find(doc => doc.id === id);
|
|
310
|
+
if (!document) {
|
|
311
|
+
throw new Error(`Document with ID ${id} not found.`);
|
|
312
|
+
}
|
|
313
|
+
return document;
|
|
288
314
|
}
|
|
289
315
|
// ============================================================================
|
|
290
316
|
// Job Catalog endpoints
|
|
@@ -293,31 +319,27 @@ export async function getDocument(id) {
|
|
|
293
319
|
* List all job roles
|
|
294
320
|
*/
|
|
295
321
|
export async function listJobRoles() {
|
|
296
|
-
return cached('job-roles:all', () => fetchList(
|
|
322
|
+
return cached('job-roles:all', () => fetchList(ENDPOINTS.jobRoles), CACHE_TTL.default);
|
|
297
323
|
}
|
|
298
324
|
/**
|
|
299
325
|
* Get a specific job role by ID
|
|
300
326
|
*/
|
|
301
327
|
export async function getJobRole(id) {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
305
|
-
return fetchOne(`/job_catalog/roles/${id}`);
|
|
328
|
+
validateId(id, 'job role');
|
|
329
|
+
return fetchOne(endpointWithId(ENDPOINTS.jobRoles, id));
|
|
306
330
|
}
|
|
307
331
|
/**
|
|
308
332
|
* List all job levels
|
|
309
333
|
*/
|
|
310
334
|
export async function listJobLevels() {
|
|
311
|
-
return cached('job-levels:all', () => fetchList(
|
|
335
|
+
return cached('job-levels:all', () => fetchList(ENDPOINTS.jobLevels), CACHE_TTL.default);
|
|
312
336
|
}
|
|
313
337
|
/**
|
|
314
338
|
* Get a specific job level by ID
|
|
315
339
|
*/
|
|
316
340
|
export async function getJobLevel(id) {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
return fetchOne(`/job_catalog/levels/${id}`);
|
|
341
|
+
validateId(id, 'job level');
|
|
342
|
+
return fetchOne(endpointWithId(ENDPOINTS.jobLevels, id));
|
|
321
343
|
}
|
|
322
344
|
// ============================================================================
|
|
323
345
|
// Cache utilities
|
|
@@ -342,7 +364,7 @@ export function invalidateCache(resourceType) {
|
|
|
342
364
|
*/
|
|
343
365
|
export async function createEmployee(input) {
|
|
344
366
|
return auditedOperation(AuditAction.CREATE, 'employee', undefined, async () => {
|
|
345
|
-
const employee = await postOne(
|
|
367
|
+
const employee = await postOne(ENDPOINTS.employees, input);
|
|
346
368
|
cache.invalidatePrefix('employees');
|
|
347
369
|
return employee;
|
|
348
370
|
}, Object.fromEntries(Object.entries(input).map(([k, v]) => [k, { to: v }])));
|
|
@@ -351,11 +373,9 @@ export async function createEmployee(input) {
|
|
|
351
373
|
* Update an existing employee
|
|
352
374
|
*/
|
|
353
375
|
export async function updateEmployee(id, input) {
|
|
354
|
-
|
|
355
|
-
throw new Error('Invalid employee ID. Please provide a positive number.');
|
|
356
|
-
}
|
|
376
|
+
validateId(id, 'employee');
|
|
357
377
|
return auditedOperation(AuditAction.UPDATE, 'employee', id, async () => {
|
|
358
|
-
const employee = await patchOne(
|
|
378
|
+
const employee = await patchOne(endpointWithId(ENDPOINTS.employees, id), input);
|
|
359
379
|
cache.invalidate(`employee:${id}`);
|
|
360
380
|
cache.invalidatePrefix('employees');
|
|
361
381
|
return employee;
|
|
@@ -365,11 +385,9 @@ export async function updateEmployee(id, input) {
|
|
|
365
385
|
* Terminate an employee (soft delete)
|
|
366
386
|
*/
|
|
367
387
|
export async function terminateEmployee(id, terminatedOn, reason) {
|
|
368
|
-
|
|
369
|
-
throw new Error('Invalid employee ID. Please provide a positive number.');
|
|
370
|
-
}
|
|
388
|
+
validateId(id, 'employee');
|
|
371
389
|
return auditedOperation(AuditAction.TERMINATE, 'employee', id, async () => {
|
|
372
|
-
const employee = await patchOne(
|
|
390
|
+
const employee = await patchOne(endpointWithId(ENDPOINTS.employees, id), {
|
|
373
391
|
terminated_on: terminatedOn,
|
|
374
392
|
});
|
|
375
393
|
cache.invalidate(`employee:${id}`);
|
|
@@ -385,7 +403,7 @@ export async function terminateEmployee(id, terminatedOn, reason) {
|
|
|
385
403
|
*/
|
|
386
404
|
export async function createTeam(input) {
|
|
387
405
|
return auditedOperation(AuditAction.CREATE, 'team', undefined, async () => {
|
|
388
|
-
const team = await postOne(
|
|
406
|
+
const team = await postOne(ENDPOINTS.teams, input);
|
|
389
407
|
cache.invalidatePrefix('teams');
|
|
390
408
|
return team;
|
|
391
409
|
});
|
|
@@ -394,11 +412,9 @@ export async function createTeam(input) {
|
|
|
394
412
|
* Update an existing team
|
|
395
413
|
*/
|
|
396
414
|
export async function updateTeam(id, input) {
|
|
397
|
-
|
|
398
|
-
throw new Error('Invalid team ID. Please provide a positive number.');
|
|
399
|
-
}
|
|
415
|
+
validateId(id, 'team');
|
|
400
416
|
return auditedOperation(AuditAction.UPDATE, 'team', id, async () => {
|
|
401
|
-
const team = await patchOne(
|
|
417
|
+
const team = await patchOne(endpointWithId(ENDPOINTS.teams, id), input);
|
|
402
418
|
cache.invalidate(`team:${id}`);
|
|
403
419
|
cache.invalidatePrefix('teams');
|
|
404
420
|
return team;
|
|
@@ -408,11 +424,9 @@ export async function updateTeam(id, input) {
|
|
|
408
424
|
* Delete a team
|
|
409
425
|
*/
|
|
410
426
|
export async function deleteTeam(id) {
|
|
411
|
-
|
|
412
|
-
throw new Error('Invalid team ID. Please provide a positive number.');
|
|
413
|
-
}
|
|
427
|
+
validateId(id, 'team');
|
|
414
428
|
return auditedOperation(AuditAction.DELETE, 'team', id, async () => {
|
|
415
|
-
await deleteOne(
|
|
429
|
+
await deleteOne(endpointWithId(ENDPOINTS.teams, id));
|
|
416
430
|
cache.invalidate(`team:${id}`);
|
|
417
431
|
cache.invalidatePrefix('teams');
|
|
418
432
|
});
|
|
@@ -425,7 +439,7 @@ export async function deleteTeam(id) {
|
|
|
425
439
|
*/
|
|
426
440
|
export async function createLocation(input) {
|
|
427
441
|
return auditedOperation(AuditAction.CREATE, 'location', undefined, async () => {
|
|
428
|
-
const location = await postOne(
|
|
442
|
+
const location = await postOne(ENDPOINTS.locations, input);
|
|
429
443
|
cache.invalidatePrefix('locations');
|
|
430
444
|
return location;
|
|
431
445
|
});
|
|
@@ -434,11 +448,9 @@ export async function createLocation(input) {
|
|
|
434
448
|
* Update an existing location
|
|
435
449
|
*/
|
|
436
450
|
export async function updateLocation(id, input) {
|
|
437
|
-
|
|
438
|
-
throw new Error('Invalid location ID. Please provide a positive number.');
|
|
439
|
-
}
|
|
451
|
+
validateId(id, 'location');
|
|
440
452
|
return auditedOperation(AuditAction.UPDATE, 'location', id, async () => {
|
|
441
|
-
const location = await patchOne(
|
|
453
|
+
const location = await patchOne(endpointWithId(ENDPOINTS.locations, id), input);
|
|
442
454
|
cache.invalidate(`location:${id}`);
|
|
443
455
|
cache.invalidatePrefix('locations');
|
|
444
456
|
return location;
|
|
@@ -448,11 +460,9 @@ export async function updateLocation(id, input) {
|
|
|
448
460
|
* Delete a location
|
|
449
461
|
*/
|
|
450
462
|
export async function deleteLocation(id) {
|
|
451
|
-
|
|
452
|
-
throw new Error('Invalid location ID. Please provide a positive number.');
|
|
453
|
-
}
|
|
463
|
+
validateId(id, 'location');
|
|
454
464
|
return auditedOperation(AuditAction.DELETE, 'location', id, async () => {
|
|
455
|
-
await deleteOne(
|
|
465
|
+
await deleteOne(endpointWithId(ENDPOINTS.locations, id));
|
|
456
466
|
cache.invalidate(`location:${id}`);
|
|
457
467
|
cache.invalidatePrefix('locations');
|
|
458
468
|
});
|
|
@@ -465,7 +475,7 @@ export async function deleteLocation(id) {
|
|
|
465
475
|
*/
|
|
466
476
|
export async function createLeave(input) {
|
|
467
477
|
return auditedOperation(AuditAction.CREATE, 'leave', undefined, async () => {
|
|
468
|
-
const leave = await postOne(
|
|
478
|
+
const leave = await postOne(ENDPOINTS.leaves, input);
|
|
469
479
|
return leave;
|
|
470
480
|
});
|
|
471
481
|
}
|
|
@@ -473,11 +483,9 @@ export async function createLeave(input) {
|
|
|
473
483
|
* Update a leave request
|
|
474
484
|
*/
|
|
475
485
|
export async function updateLeave(id, input) {
|
|
476
|
-
|
|
477
|
-
throw new Error('Invalid leave ID. Please provide a positive number.');
|
|
478
|
-
}
|
|
486
|
+
validateId(id, 'leave');
|
|
479
487
|
return auditedOperation(AuditAction.UPDATE, 'leave', id, async () => {
|
|
480
|
-
const leave = await patchOne(
|
|
488
|
+
const leave = await patchOne(endpointWithId(ENDPOINTS.leaves, id), input);
|
|
481
489
|
return leave;
|
|
482
490
|
});
|
|
483
491
|
}
|
|
@@ -485,22 +493,18 @@ export async function updateLeave(id, input) {
|
|
|
485
493
|
* Cancel a leave request
|
|
486
494
|
*/
|
|
487
495
|
export async function cancelLeave(id) {
|
|
488
|
-
|
|
489
|
-
throw new Error('Invalid leave ID. Please provide a positive number.');
|
|
490
|
-
}
|
|
496
|
+
validateId(id, 'leave');
|
|
491
497
|
return auditedOperation(AuditAction.DELETE, 'leave', id, async () => {
|
|
492
|
-
await deleteOne(
|
|
498
|
+
await deleteOne(endpointWithId(ENDPOINTS.leaves, id));
|
|
493
499
|
});
|
|
494
500
|
}
|
|
495
501
|
/**
|
|
496
502
|
* Approve a leave request
|
|
497
503
|
*/
|
|
498
504
|
export async function approveLeave(id, input) {
|
|
499
|
-
|
|
500
|
-
throw new Error('Invalid leave ID. Please provide a positive number.');
|
|
501
|
-
}
|
|
505
|
+
validateId(id, 'leave');
|
|
502
506
|
return auditedOperation(AuditAction.APPROVE, 'leave', id, async () => {
|
|
503
|
-
const leave = await postAction(
|
|
507
|
+
const leave = await postAction(endpointWithAction(ENDPOINTS.leaves, id, 'approve'), input || {});
|
|
504
508
|
return leave;
|
|
505
509
|
});
|
|
506
510
|
}
|
|
@@ -508,11 +512,9 @@ export async function approveLeave(id, input) {
|
|
|
508
512
|
* Reject a leave request
|
|
509
513
|
*/
|
|
510
514
|
export async function rejectLeave(id, input) {
|
|
511
|
-
|
|
512
|
-
throw new Error('Invalid leave ID. Please provide a positive number.');
|
|
513
|
-
}
|
|
515
|
+
validateId(id, 'leave');
|
|
514
516
|
return auditedOperation(AuditAction.REJECT, 'leave', id, async () => {
|
|
515
|
-
const leave = await postAction(
|
|
517
|
+
const leave = await postAction(endpointWithAction(ENDPOINTS.leaves, id, 'reject'), input || {});
|
|
516
518
|
return leave;
|
|
517
519
|
});
|
|
518
520
|
}
|
|
@@ -524,7 +526,7 @@ export async function rejectLeave(id, input) {
|
|
|
524
526
|
*/
|
|
525
527
|
export async function createShift(input) {
|
|
526
528
|
return auditedOperation(AuditAction.CREATE, 'shift', undefined, async () => {
|
|
527
|
-
const shift = await postOne(
|
|
529
|
+
const shift = await postOne(ENDPOINTS.shifts, input);
|
|
528
530
|
return shift;
|
|
529
531
|
});
|
|
530
532
|
}
|
|
@@ -532,11 +534,9 @@ export async function createShift(input) {
|
|
|
532
534
|
* Update a shift
|
|
533
535
|
*/
|
|
534
536
|
export async function updateShift(id, input) {
|
|
535
|
-
|
|
536
|
-
throw new Error('Invalid shift ID. Please provide a positive number.');
|
|
537
|
-
}
|
|
537
|
+
validateId(id, 'shift');
|
|
538
538
|
return auditedOperation(AuditAction.UPDATE, 'shift', id, async () => {
|
|
539
|
-
const shift = await patchOne(
|
|
539
|
+
const shift = await patchOne(endpointWithId(ENDPOINTS.shifts, id), input);
|
|
540
540
|
return shift;
|
|
541
541
|
});
|
|
542
542
|
}
|
|
@@ -544,11 +544,9 @@ export async function updateShift(id, input) {
|
|
|
544
544
|
* Delete a shift
|
|
545
545
|
*/
|
|
546
546
|
export async function deleteShift(id) {
|
|
547
|
-
|
|
548
|
-
throw new Error('Invalid shift ID. Please provide a positive number.');
|
|
549
|
-
}
|
|
547
|
+
validateId(id, 'shift');
|
|
550
548
|
return auditedOperation(AuditAction.DELETE, 'shift', id, async () => {
|
|
551
|
-
await deleteOne(
|
|
549
|
+
await deleteOne(endpointWithId(ENDPOINTS.shifts, id));
|
|
552
550
|
});
|
|
553
551
|
}
|
|
554
552
|
// ============================================================================
|
|
@@ -559,17 +557,15 @@ export async function deleteShift(id) {
|
|
|
559
557
|
*/
|
|
560
558
|
export async function listProjects(options) {
|
|
561
559
|
const params = buildPaginationParams(options);
|
|
562
|
-
const projects = await cached(CacheManager.key('projects', options), () => fetchList(
|
|
560
|
+
const projects = await cached(CacheManager.key('projects', options), () => fetchList(ENDPOINTS.projects), CACHE_TTL.default);
|
|
563
561
|
return sliceForPagination(projects, params);
|
|
564
562
|
}
|
|
565
563
|
/**
|
|
566
564
|
* Get a specific project by ID
|
|
567
565
|
*/
|
|
568
566
|
export async function getProject(id) {
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
}
|
|
572
|
-
return cached(`project:${id}`, () => fetchOne(`/project_management/projects/${id}`), CACHE_TTL.default);
|
|
567
|
+
validateId(id, 'project');
|
|
568
|
+
return cached(`project:${id}`, () => fetchOne(endpointWithId(ENDPOINTS.projects, id)), CACHE_TTL.default);
|
|
573
569
|
}
|
|
574
570
|
/**
|
|
575
571
|
* List project tasks
|
|
@@ -579,7 +575,7 @@ export async function listProjectTasks(projectId, options) {
|
|
|
579
575
|
const queryParams = {};
|
|
580
576
|
if (projectId)
|
|
581
577
|
queryParams.project_ids = projectId;
|
|
582
|
-
const tasks = await fetchList(
|
|
578
|
+
const tasks = await fetchList(ENDPOINTS.projectTasks, {
|
|
583
579
|
params: queryParams,
|
|
584
580
|
});
|
|
585
581
|
return sliceForPagination(tasks, params);
|
|
@@ -588,10 +584,8 @@ export async function listProjectTasks(projectId, options) {
|
|
|
588
584
|
* Get a specific project task by ID
|
|
589
585
|
*/
|
|
590
586
|
export async function getProjectTask(id) {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
}
|
|
594
|
-
return fetchOne(`/project_management/project_tasks/${id}`);
|
|
587
|
+
validateId(id, 'task');
|
|
588
|
+
return fetchOne(endpointWithId(ENDPOINTS.projectTasks, id));
|
|
595
589
|
}
|
|
596
590
|
/**
|
|
597
591
|
* List project workers
|
|
@@ -601,7 +595,7 @@ export async function listProjectWorkers(projectId, options) {
|
|
|
601
595
|
const queryParams = {};
|
|
602
596
|
if (projectId)
|
|
603
597
|
queryParams.project_ids = projectId;
|
|
604
|
-
const workers = await fetchList(
|
|
598
|
+
const workers = await fetchList(ENDPOINTS.projectWorkers, {
|
|
605
599
|
params: queryParams,
|
|
606
600
|
});
|
|
607
601
|
return sliceForPagination(workers, params);
|
|
@@ -610,10 +604,8 @@ export async function listProjectWorkers(projectId, options) {
|
|
|
610
604
|
* Get a specific project worker by ID
|
|
611
605
|
*/
|
|
612
606
|
export async function getProjectWorker(id) {
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
}
|
|
616
|
-
return fetchOne(`/project_management/project_workers/${id}`);
|
|
607
|
+
validateId(id, 'project worker');
|
|
608
|
+
return fetchOne(endpointWithId(ENDPOINTS.projectWorkers, id));
|
|
617
609
|
}
|
|
618
610
|
/**
|
|
619
611
|
* List time records
|
|
@@ -623,7 +615,7 @@ export async function listTimeRecords(projectWorkerId, options) {
|
|
|
623
615
|
const queryParams = {};
|
|
624
616
|
if (projectWorkerId)
|
|
625
617
|
queryParams.project_workers_ids = projectWorkerId;
|
|
626
|
-
const records = await fetchList(
|
|
618
|
+
const records = await fetchList(ENDPOINTS.timeRecords, {
|
|
627
619
|
params: queryParams,
|
|
628
620
|
});
|
|
629
621
|
return sliceForPagination(records, params);
|
|
@@ -632,10 +624,8 @@ export async function listTimeRecords(projectWorkerId, options) {
|
|
|
632
624
|
* Get a specific time record by ID
|
|
633
625
|
*/
|
|
634
626
|
export async function getTimeRecord(id) {
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
}
|
|
638
|
-
return fetchOne(`/project_management/time_records/${id}`);
|
|
627
|
+
validateId(id, 'time record');
|
|
628
|
+
return fetchOne(endpointWithId(ENDPOINTS.timeRecords, id));
|
|
639
629
|
}
|
|
640
630
|
// ============================================================================
|
|
641
631
|
// Projects & Time Tracking - WRITE endpoints
|
|
@@ -645,7 +635,7 @@ export async function getTimeRecord(id) {
|
|
|
645
635
|
*/
|
|
646
636
|
export async function createProject(input) {
|
|
647
637
|
return auditedOperation(AuditAction.CREATE, 'project', undefined, async () => {
|
|
648
|
-
const project = await postOne(
|
|
638
|
+
const project = await postOne(ENDPOINTS.projects, input);
|
|
649
639
|
cache.invalidatePrefix('projects');
|
|
650
640
|
return project;
|
|
651
641
|
});
|
|
@@ -654,11 +644,9 @@ export async function createProject(input) {
|
|
|
654
644
|
* Update a project
|
|
655
645
|
*/
|
|
656
646
|
export async function updateProject(id, input) {
|
|
657
|
-
|
|
658
|
-
throw new Error('Invalid project ID. Please provide a positive number.');
|
|
659
|
-
}
|
|
647
|
+
validateId(id, 'project');
|
|
660
648
|
return auditedOperation(AuditAction.UPDATE, 'project', id, async () => {
|
|
661
|
-
const project = await patchOne(
|
|
649
|
+
const project = await patchOne(endpointWithId(ENDPOINTS.projects, id), input);
|
|
662
650
|
cache.invalidate(`project:${id}`);
|
|
663
651
|
cache.invalidatePrefix('projects');
|
|
664
652
|
return project;
|
|
@@ -668,11 +656,9 @@ export async function updateProject(id, input) {
|
|
|
668
656
|
* Delete a project
|
|
669
657
|
*/
|
|
670
658
|
export async function deleteProject(id) {
|
|
671
|
-
|
|
672
|
-
throw new Error('Invalid project ID. Please provide a positive number.');
|
|
673
|
-
}
|
|
659
|
+
validateId(id, 'project');
|
|
674
660
|
return auditedOperation(AuditAction.DELETE, 'project', id, async () => {
|
|
675
|
-
await deleteOne(
|
|
661
|
+
await deleteOne(endpointWithId(ENDPOINTS.projects, id));
|
|
676
662
|
cache.invalidate(`project:${id}`);
|
|
677
663
|
cache.invalidatePrefix('projects');
|
|
678
664
|
});
|
|
@@ -682,29 +668,25 @@ export async function deleteProject(id) {
|
|
|
682
668
|
*/
|
|
683
669
|
export async function createProjectTask(input) {
|
|
684
670
|
return auditedOperation(AuditAction.CREATE, 'project_task', undefined, async () => {
|
|
685
|
-
return postOne(
|
|
671
|
+
return postOne(ENDPOINTS.projectTasks, input);
|
|
686
672
|
});
|
|
687
673
|
}
|
|
688
674
|
/**
|
|
689
675
|
* Update a project task
|
|
690
676
|
*/
|
|
691
677
|
export async function updateProjectTask(id, input) {
|
|
692
|
-
|
|
693
|
-
throw new Error('Invalid task ID. Please provide a positive number.');
|
|
694
|
-
}
|
|
678
|
+
validateId(id, 'task');
|
|
695
679
|
return auditedOperation(AuditAction.UPDATE, 'project_task', id, async () => {
|
|
696
|
-
return patchOne(
|
|
680
|
+
return patchOne(endpointWithId(ENDPOINTS.projectTasks, id), input);
|
|
697
681
|
});
|
|
698
682
|
}
|
|
699
683
|
/**
|
|
700
684
|
* Delete a project task
|
|
701
685
|
*/
|
|
702
686
|
export async function deleteProjectTask(id) {
|
|
703
|
-
|
|
704
|
-
throw new Error('Invalid task ID. Please provide a positive number.');
|
|
705
|
-
}
|
|
687
|
+
validateId(id, 'task');
|
|
706
688
|
return auditedOperation(AuditAction.DELETE, 'project_task', id, async () => {
|
|
707
|
-
await deleteOne(
|
|
689
|
+
await deleteOne(endpointWithId(ENDPOINTS.projectTasks, id));
|
|
708
690
|
});
|
|
709
691
|
}
|
|
710
692
|
/**
|
|
@@ -712,18 +694,16 @@ export async function deleteProjectTask(id) {
|
|
|
712
694
|
*/
|
|
713
695
|
export async function assignProjectWorker(input) {
|
|
714
696
|
return auditedOperation(AuditAction.ASSIGN, 'project_worker', undefined, async () => {
|
|
715
|
-
return postOne(
|
|
697
|
+
return postOne(ENDPOINTS.projectWorkers, input);
|
|
716
698
|
});
|
|
717
699
|
}
|
|
718
700
|
/**
|
|
719
701
|
* Remove a worker from a project
|
|
720
702
|
*/
|
|
721
703
|
export async function removeProjectWorker(id) {
|
|
722
|
-
|
|
723
|
-
throw new Error('Invalid project worker ID. Please provide a positive number.');
|
|
724
|
-
}
|
|
704
|
+
validateId(id, 'project worker');
|
|
725
705
|
return auditedOperation(AuditAction.UNASSIGN, 'project_worker', id, async () => {
|
|
726
|
-
await deleteOne(
|
|
706
|
+
await deleteOne(endpointWithId(ENDPOINTS.projectWorkers, id));
|
|
727
707
|
});
|
|
728
708
|
}
|
|
729
709
|
/**
|
|
@@ -731,29 +711,25 @@ export async function removeProjectWorker(id) {
|
|
|
731
711
|
*/
|
|
732
712
|
export async function createTimeRecord(input) {
|
|
733
713
|
return auditedOperation(AuditAction.CREATE, 'time_record', undefined, async () => {
|
|
734
|
-
return postOne(
|
|
714
|
+
return postOne(ENDPOINTS.timeRecords, input);
|
|
735
715
|
});
|
|
736
716
|
}
|
|
737
717
|
/**
|
|
738
718
|
* Update a time record
|
|
739
719
|
*/
|
|
740
720
|
export async function updateTimeRecord(id, input) {
|
|
741
|
-
|
|
742
|
-
throw new Error('Invalid time record ID. Please provide a positive number.');
|
|
743
|
-
}
|
|
721
|
+
validateId(id, 'time record');
|
|
744
722
|
return auditedOperation(AuditAction.UPDATE, 'time_record', id, async () => {
|
|
745
|
-
return patchOne(
|
|
723
|
+
return patchOne(endpointWithId(ENDPOINTS.timeRecords, id), input);
|
|
746
724
|
});
|
|
747
725
|
}
|
|
748
726
|
/**
|
|
749
727
|
* Delete a time record
|
|
750
728
|
*/
|
|
751
729
|
export async function deleteTimeRecord(id) {
|
|
752
|
-
|
|
753
|
-
throw new Error('Invalid time record ID. Please provide a positive number.');
|
|
754
|
-
}
|
|
730
|
+
validateId(id, 'time record');
|
|
755
731
|
return auditedOperation(AuditAction.DELETE, 'time_record', id, async () => {
|
|
756
|
-
await deleteOne(
|
|
732
|
+
await deleteOne(endpointWithId(ENDPOINTS.timeRecords, id));
|
|
757
733
|
});
|
|
758
734
|
}
|
|
759
735
|
// ============================================================================
|
|
@@ -764,17 +740,15 @@ export async function deleteTimeRecord(id) {
|
|
|
764
740
|
*/
|
|
765
741
|
export async function listTrainings(options) {
|
|
766
742
|
const params = buildPaginationParams(options);
|
|
767
|
-
const trainings = await cached(CacheManager.key('trainings', options), () => fetchList(
|
|
743
|
+
const trainings = await cached(CacheManager.key('trainings', options), () => fetchList(ENDPOINTS.trainings), CACHE_TTL.default);
|
|
768
744
|
return sliceForPagination(trainings, params);
|
|
769
745
|
}
|
|
770
746
|
/**
|
|
771
747
|
* Get a specific training by ID
|
|
772
748
|
*/
|
|
773
749
|
export async function getTraining(id) {
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
}
|
|
777
|
-
return cached(`training:${id}`, () => fetchOne(`/trainings/trainings/${id}`), CACHE_TTL.default);
|
|
750
|
+
validateId(id, 'training');
|
|
751
|
+
return cached(`training:${id}`, () => fetchOne(endpointWithId(ENDPOINTS.trainings, id)), CACHE_TTL.default);
|
|
778
752
|
}
|
|
779
753
|
/**
|
|
780
754
|
* List training sessions
|
|
@@ -784,17 +758,17 @@ export async function listTrainingSessions(trainingId, options) {
|
|
|
784
758
|
const queryParams = {};
|
|
785
759
|
if (trainingId)
|
|
786
760
|
queryParams.training_id = trainingId;
|
|
787
|
-
const sessions = await fetchList(
|
|
761
|
+
const sessions = await fetchList(ENDPOINTS.trainingSessions, {
|
|
762
|
+
params: queryParams,
|
|
763
|
+
});
|
|
788
764
|
return sliceForPagination(sessions, params);
|
|
789
765
|
}
|
|
790
766
|
/**
|
|
791
767
|
* Get a specific training session by ID
|
|
792
768
|
*/
|
|
793
769
|
export async function getTrainingSession(id) {
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
}
|
|
797
|
-
return fetchOne(`/trainings/sessions/${id}`);
|
|
770
|
+
validateId(id, 'session');
|
|
771
|
+
return fetchOne(endpointWithId(ENDPOINTS.trainingSessions, id));
|
|
798
772
|
}
|
|
799
773
|
/**
|
|
800
774
|
* List training enrollments
|
|
@@ -804,7 +778,7 @@ export async function listTrainingEnrollments(trainingId, options) {
|
|
|
804
778
|
const queryParams = {};
|
|
805
779
|
if (trainingId)
|
|
806
780
|
queryParams.training_id = trainingId;
|
|
807
|
-
const enrollments = await fetchList(
|
|
781
|
+
const enrollments = await fetchList(ENDPOINTS.trainingMemberships, {
|
|
808
782
|
params: queryParams,
|
|
809
783
|
});
|
|
810
784
|
return sliceForPagination(enrollments, params);
|
|
@@ -813,10 +787,8 @@ export async function listTrainingEnrollments(trainingId, options) {
|
|
|
813
787
|
* Get a specific training enrollment by ID
|
|
814
788
|
*/
|
|
815
789
|
export async function getTrainingEnrollment(id) {
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
}
|
|
819
|
-
return fetchOne(`/trainings/memberships/${id}`);
|
|
790
|
+
validateId(id, 'enrollment');
|
|
791
|
+
return fetchOne(endpointWithId(ENDPOINTS.trainingMemberships, id));
|
|
820
792
|
}
|
|
821
793
|
// ============================================================================
|
|
822
794
|
// Training & Development - WRITE endpoints
|
|
@@ -826,7 +798,7 @@ export async function getTrainingEnrollment(id) {
|
|
|
826
798
|
*/
|
|
827
799
|
export async function createTraining(input) {
|
|
828
800
|
return auditedOperation(AuditAction.CREATE, 'training', undefined, async () => {
|
|
829
|
-
const training = await postOne(
|
|
801
|
+
const training = await postOne(ENDPOINTS.trainings, input);
|
|
830
802
|
cache.invalidatePrefix('trainings');
|
|
831
803
|
return training;
|
|
832
804
|
});
|
|
@@ -835,11 +807,9 @@ export async function createTraining(input) {
|
|
|
835
807
|
* Update a training program
|
|
836
808
|
*/
|
|
837
809
|
export async function updateTraining(id, input) {
|
|
838
|
-
|
|
839
|
-
throw new Error('Invalid training ID. Please provide a positive number.');
|
|
840
|
-
}
|
|
810
|
+
validateId(id, 'training');
|
|
841
811
|
return auditedOperation(AuditAction.UPDATE, 'training', id, async () => {
|
|
842
|
-
const training = await patchOne(
|
|
812
|
+
const training = await patchOne(endpointWithId(ENDPOINTS.trainings, id), input);
|
|
843
813
|
cache.invalidate(`training:${id}`);
|
|
844
814
|
cache.invalidatePrefix('trainings');
|
|
845
815
|
return training;
|
|
@@ -849,11 +819,9 @@ export async function updateTraining(id, input) {
|
|
|
849
819
|
* Delete a training program
|
|
850
820
|
*/
|
|
851
821
|
export async function deleteTraining(id) {
|
|
852
|
-
|
|
853
|
-
throw new Error('Invalid training ID. Please provide a positive number.');
|
|
854
|
-
}
|
|
822
|
+
validateId(id, 'training');
|
|
855
823
|
return auditedOperation(AuditAction.DELETE, 'training', id, async () => {
|
|
856
|
-
await deleteOne(
|
|
824
|
+
await deleteOne(endpointWithId(ENDPOINTS.trainings, id));
|
|
857
825
|
cache.invalidate(`training:${id}`);
|
|
858
826
|
cache.invalidatePrefix('trainings');
|
|
859
827
|
});
|
|
@@ -863,29 +831,25 @@ export async function deleteTraining(id) {
|
|
|
863
831
|
*/
|
|
864
832
|
export async function createTrainingSession(input) {
|
|
865
833
|
return auditedOperation(AuditAction.CREATE, 'training_session', undefined, async () => {
|
|
866
|
-
return postOne(
|
|
834
|
+
return postOne(ENDPOINTS.trainingSessions, input);
|
|
867
835
|
});
|
|
868
836
|
}
|
|
869
837
|
/**
|
|
870
838
|
* Update a training session
|
|
871
839
|
*/
|
|
872
840
|
export async function updateTrainingSession(id, input) {
|
|
873
|
-
|
|
874
|
-
throw new Error('Invalid session ID. Please provide a positive number.');
|
|
875
|
-
}
|
|
841
|
+
validateId(id, 'session');
|
|
876
842
|
return auditedOperation(AuditAction.UPDATE, 'training_session', id, async () => {
|
|
877
|
-
return patchOne(
|
|
843
|
+
return patchOne(endpointWithId(ENDPOINTS.trainingSessions, id), input);
|
|
878
844
|
});
|
|
879
845
|
}
|
|
880
846
|
/**
|
|
881
847
|
* Delete a training session
|
|
882
848
|
*/
|
|
883
849
|
export async function deleteTrainingSession(id) {
|
|
884
|
-
|
|
885
|
-
throw new Error('Invalid session ID. Please provide a positive number.');
|
|
886
|
-
}
|
|
850
|
+
validateId(id, 'session');
|
|
887
851
|
return auditedOperation(AuditAction.DELETE, 'training_session', id, async () => {
|
|
888
|
-
await deleteOne(
|
|
852
|
+
await deleteOne(endpointWithId(ENDPOINTS.trainingSessions, id));
|
|
889
853
|
});
|
|
890
854
|
}
|
|
891
855
|
/**
|
|
@@ -893,18 +857,16 @@ export async function deleteTrainingSession(id) {
|
|
|
893
857
|
*/
|
|
894
858
|
export async function enrollInTraining(input) {
|
|
895
859
|
return auditedOperation(AuditAction.ASSIGN, 'training_enrollment', undefined, async () => {
|
|
896
|
-
return postOne(
|
|
860
|
+
return postOne(ENDPOINTS.trainingMemberships, input);
|
|
897
861
|
});
|
|
898
862
|
}
|
|
899
863
|
/**
|
|
900
864
|
* Remove enrollment from a training
|
|
901
865
|
*/
|
|
902
866
|
export async function unenrollFromTraining(id) {
|
|
903
|
-
|
|
904
|
-
throw new Error('Invalid enrollment ID. Please provide a positive number.');
|
|
905
|
-
}
|
|
867
|
+
validateId(id, 'enrollment');
|
|
906
868
|
return auditedOperation(AuditAction.UNASSIGN, 'training_enrollment', id, async () => {
|
|
907
|
-
await deleteOne(
|
|
869
|
+
await deleteOne(endpointWithId(ENDPOINTS.trainingMemberships, id));
|
|
908
870
|
});
|
|
909
871
|
}
|
|
910
872
|
// ============================================================================
|
|
@@ -915,24 +877,22 @@ export async function unenrollFromTraining(id) {
|
|
|
915
877
|
*/
|
|
916
878
|
export async function listWorkAreas(options) {
|
|
917
879
|
const params = buildPaginationParams(options);
|
|
918
|
-
const workAreas = await cached(CacheManager.key('work_areas', options), () => fetchList(
|
|
880
|
+
const workAreas = await cached(CacheManager.key('work_areas', options), () => fetchList(ENDPOINTS.workAreas), CACHE_TTL.locations);
|
|
919
881
|
return sliceForPagination(workAreas, params);
|
|
920
882
|
}
|
|
921
883
|
/**
|
|
922
884
|
* Get a specific work area by ID
|
|
923
885
|
*/
|
|
924
886
|
export async function getWorkArea(id) {
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
}
|
|
928
|
-
return cached(`work_area:${id}`, () => fetchOne(`/locations/work_areas/${id}`), CACHE_TTL.locations);
|
|
887
|
+
validateId(id, 'work area');
|
|
888
|
+
return cached(`work_area:${id}`, () => fetchOne(endpointWithId(ENDPOINTS.workAreas, id)), CACHE_TTL.locations);
|
|
929
889
|
}
|
|
930
890
|
/**
|
|
931
891
|
* Create a work area
|
|
932
892
|
*/
|
|
933
893
|
export async function createWorkArea(input) {
|
|
934
894
|
return auditedOperation(AuditAction.CREATE, 'work_area', undefined, async () => {
|
|
935
|
-
const workArea = await postOne(
|
|
895
|
+
const workArea = await postOne(ENDPOINTS.workAreas, input);
|
|
936
896
|
cache.invalidatePrefix('work_areas');
|
|
937
897
|
return workArea;
|
|
938
898
|
});
|
|
@@ -941,11 +901,9 @@ export async function createWorkArea(input) {
|
|
|
941
901
|
* Update a work area
|
|
942
902
|
*/
|
|
943
903
|
export async function updateWorkArea(id, input) {
|
|
944
|
-
|
|
945
|
-
throw new Error('Invalid work area ID. Please provide a positive number.');
|
|
946
|
-
}
|
|
904
|
+
validateId(id, 'work area');
|
|
947
905
|
return auditedOperation(AuditAction.UPDATE, 'work_area', id, async () => {
|
|
948
|
-
const workArea = await patchOne(
|
|
906
|
+
const workArea = await patchOne(endpointWithId(ENDPOINTS.workAreas, id), input);
|
|
949
907
|
cache.invalidate(`work_area:${id}`);
|
|
950
908
|
cache.invalidatePrefix('work_areas');
|
|
951
909
|
return workArea;
|
|
@@ -955,11 +913,9 @@ export async function updateWorkArea(id, input) {
|
|
|
955
913
|
* Archive a work area
|
|
956
914
|
*/
|
|
957
915
|
export async function archiveWorkArea(id) {
|
|
958
|
-
|
|
959
|
-
throw new Error('Invalid work area ID. Please provide a positive number.');
|
|
960
|
-
}
|
|
916
|
+
validateId(id, 'work area');
|
|
961
917
|
return auditedOperation(AuditAction.ARCHIVE, 'work_area', id, async () => {
|
|
962
|
-
const workArea = await postAction(
|
|
918
|
+
const workArea = await postAction(endpointWithAction(ENDPOINTS.workAreas, id, 'archive'));
|
|
963
919
|
cache.invalidate(`work_area:${id}`);
|
|
964
920
|
cache.invalidatePrefix('work_areas');
|
|
965
921
|
return workArea;
|
|
@@ -969,11 +925,9 @@ export async function archiveWorkArea(id) {
|
|
|
969
925
|
* Unarchive a work area
|
|
970
926
|
*/
|
|
971
927
|
export async function unarchiveWorkArea(id) {
|
|
972
|
-
|
|
973
|
-
throw new Error('Invalid work area ID. Please provide a positive number.');
|
|
974
|
-
}
|
|
928
|
+
validateId(id, 'work area');
|
|
975
929
|
return auditedOperation(AuditAction.UNARCHIVE, 'work_area', id, async () => {
|
|
976
|
-
const workArea = await postAction(
|
|
930
|
+
const workArea = await postAction(endpointWithAction(ENDPOINTS.workAreas, id, 'unarchive'));
|
|
977
931
|
cache.invalidate(`work_area:${id}`);
|
|
978
932
|
cache.invalidatePrefix('work_areas');
|
|
979
933
|
return workArea;
|
|
@@ -987,34 +941,30 @@ export async function unarchiveWorkArea(id) {
|
|
|
987
941
|
*/
|
|
988
942
|
export async function listJobPostings(options) {
|
|
989
943
|
const params = buildPaginationParams(options);
|
|
990
|
-
const postings = await cached(CacheManager.key('job_postings', options), () => fetchList(
|
|
944
|
+
const postings = await cached(CacheManager.key('job_postings', options), () => fetchList(ENDPOINTS.jobPostings), CACHE_TTL.default);
|
|
991
945
|
return sliceForPagination(postings, params);
|
|
992
946
|
}
|
|
993
947
|
/**
|
|
994
948
|
* Get a specific job posting by ID
|
|
995
949
|
*/
|
|
996
950
|
export async function getJobPosting(id) {
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
}
|
|
1000
|
-
return cached(`job_posting:${id}`, () => fetchOne(`/ats/job_postings/${id}`), CACHE_TTL.default);
|
|
951
|
+
validateId(id, 'job posting');
|
|
952
|
+
return cached(`job_posting:${id}`, () => fetchOne(endpointWithId(ENDPOINTS.jobPostings, id)), CACHE_TTL.default);
|
|
1001
953
|
}
|
|
1002
954
|
/**
|
|
1003
955
|
* List all candidates
|
|
1004
956
|
*/
|
|
1005
957
|
export async function listCandidates(options) {
|
|
1006
958
|
const params = buildPaginationParams(options);
|
|
1007
|
-
const candidates = await fetchList(
|
|
959
|
+
const candidates = await fetchList(ENDPOINTS.candidates);
|
|
1008
960
|
return sliceForPagination(candidates, params);
|
|
1009
961
|
}
|
|
1010
962
|
/**
|
|
1011
963
|
* Get a specific candidate by ID
|
|
1012
964
|
*/
|
|
1013
965
|
export async function getCandidate(id) {
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
}
|
|
1017
|
-
return fetchOne(`/ats/candidates/${id}`);
|
|
966
|
+
validateId(id, 'candidate');
|
|
967
|
+
return fetchOne(endpointWithId(ENDPOINTS.candidates, id));
|
|
1018
968
|
}
|
|
1019
969
|
/**
|
|
1020
970
|
* List all applications
|
|
@@ -1024,32 +974,30 @@ export async function listApplications(jobPostingId, options) {
|
|
|
1024
974
|
const queryParams = {};
|
|
1025
975
|
if (jobPostingId)
|
|
1026
976
|
queryParams.job_posting_id = jobPostingId;
|
|
1027
|
-
const applications = await fetchList(
|
|
977
|
+
const applications = await fetchList(ENDPOINTS.applications, {
|
|
978
|
+
params: queryParams,
|
|
979
|
+
});
|
|
1028
980
|
return sliceForPagination(applications, params);
|
|
1029
981
|
}
|
|
1030
982
|
/**
|
|
1031
983
|
* Get a specific application by ID
|
|
1032
984
|
*/
|
|
1033
985
|
export async function getApplication(id) {
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
}
|
|
1037
|
-
return fetchOne(`/ats/applications/${id}`);
|
|
986
|
+
validateId(id, 'application');
|
|
987
|
+
return fetchOne(endpointWithId(ENDPOINTS.applications, id));
|
|
1038
988
|
}
|
|
1039
989
|
/**
|
|
1040
990
|
* List all hiring stages
|
|
1041
991
|
*/
|
|
1042
992
|
export async function listHiringStages() {
|
|
1043
|
-
return cached('hiring_stages:all', () => fetchList(
|
|
993
|
+
return cached('hiring_stages:all', () => fetchList(ENDPOINTS.hiringStages), CACHE_TTL.default);
|
|
1044
994
|
}
|
|
1045
995
|
/**
|
|
1046
996
|
* Get a specific hiring stage by ID
|
|
1047
997
|
*/
|
|
1048
998
|
export async function getHiringStage(id) {
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
}
|
|
1052
|
-
return fetchOne(`/ats/hiring_stages/${id}`);
|
|
999
|
+
validateId(id, 'hiring stage');
|
|
1000
|
+
return fetchOne(endpointWithId(ENDPOINTS.hiringStages, id));
|
|
1053
1001
|
}
|
|
1054
1002
|
// ============================================================================
|
|
1055
1003
|
// ATS (Recruiting) - WRITE endpoints
|
|
@@ -1059,7 +1007,7 @@ export async function getHiringStage(id) {
|
|
|
1059
1007
|
*/
|
|
1060
1008
|
export async function createJobPosting(input) {
|
|
1061
1009
|
return auditedOperation(AuditAction.CREATE, 'job_posting', undefined, async () => {
|
|
1062
|
-
const posting = await postOne(
|
|
1010
|
+
const posting = await postOne(ENDPOINTS.jobPostings, input);
|
|
1063
1011
|
cache.invalidatePrefix('job_postings');
|
|
1064
1012
|
return posting;
|
|
1065
1013
|
});
|
|
@@ -1068,11 +1016,9 @@ export async function createJobPosting(input) {
|
|
|
1068
1016
|
* Update a job posting
|
|
1069
1017
|
*/
|
|
1070
1018
|
export async function updateJobPosting(id, input) {
|
|
1071
|
-
|
|
1072
|
-
throw new Error('Invalid job posting ID. Please provide a positive number.');
|
|
1073
|
-
}
|
|
1019
|
+
validateId(id, 'job posting');
|
|
1074
1020
|
return auditedOperation(AuditAction.UPDATE, 'job_posting', id, async () => {
|
|
1075
|
-
const posting = await patchOne(
|
|
1021
|
+
const posting = await patchOne(endpointWithId(ENDPOINTS.jobPostings, id), input);
|
|
1076
1022
|
cache.invalidate(`job_posting:${id}`);
|
|
1077
1023
|
cache.invalidatePrefix('job_postings');
|
|
1078
1024
|
return posting;
|
|
@@ -1082,11 +1028,9 @@ export async function updateJobPosting(id, input) {
|
|
|
1082
1028
|
* Delete a job posting
|
|
1083
1029
|
*/
|
|
1084
1030
|
export async function deleteJobPosting(id) {
|
|
1085
|
-
|
|
1086
|
-
throw new Error('Invalid job posting ID. Please provide a positive number.');
|
|
1087
|
-
}
|
|
1031
|
+
validateId(id, 'job posting');
|
|
1088
1032
|
return auditedOperation(AuditAction.DELETE, 'job_posting', id, async () => {
|
|
1089
|
-
await deleteOne(
|
|
1033
|
+
await deleteOne(endpointWithId(ENDPOINTS.jobPostings, id));
|
|
1090
1034
|
cache.invalidate(`job_posting:${id}`);
|
|
1091
1035
|
cache.invalidatePrefix('job_postings');
|
|
1092
1036
|
});
|
|
@@ -1096,29 +1040,25 @@ export async function deleteJobPosting(id) {
|
|
|
1096
1040
|
*/
|
|
1097
1041
|
export async function createCandidate(input) {
|
|
1098
1042
|
return auditedOperation(AuditAction.CREATE, 'candidate', undefined, async () => {
|
|
1099
|
-
return postOne(
|
|
1043
|
+
return postOne(ENDPOINTS.candidates, input);
|
|
1100
1044
|
});
|
|
1101
1045
|
}
|
|
1102
1046
|
/**
|
|
1103
1047
|
* Update a candidate
|
|
1104
1048
|
*/
|
|
1105
1049
|
export async function updateCandidate(id, input) {
|
|
1106
|
-
|
|
1107
|
-
throw new Error('Invalid candidate ID. Please provide a positive number.');
|
|
1108
|
-
}
|
|
1050
|
+
validateId(id, 'candidate');
|
|
1109
1051
|
return auditedOperation(AuditAction.UPDATE, 'candidate', id, async () => {
|
|
1110
|
-
return patchOne(
|
|
1052
|
+
return patchOne(endpointWithId(ENDPOINTS.candidates, id), input);
|
|
1111
1053
|
});
|
|
1112
1054
|
}
|
|
1113
1055
|
/**
|
|
1114
1056
|
* Delete a candidate
|
|
1115
1057
|
*/
|
|
1116
1058
|
export async function deleteCandidate(id) {
|
|
1117
|
-
|
|
1118
|
-
throw new Error('Invalid candidate ID. Please provide a positive number.');
|
|
1119
|
-
}
|
|
1059
|
+
validateId(id, 'candidate');
|
|
1120
1060
|
return auditedOperation(AuditAction.DELETE, 'candidate', id, async () => {
|
|
1121
|
-
await deleteOne(
|
|
1061
|
+
await deleteOne(endpointWithId(ENDPOINTS.candidates, id));
|
|
1122
1062
|
});
|
|
1123
1063
|
}
|
|
1124
1064
|
/**
|
|
@@ -1126,40 +1066,34 @@ export async function deleteCandidate(id) {
|
|
|
1126
1066
|
*/
|
|
1127
1067
|
export async function createApplication(input) {
|
|
1128
1068
|
return auditedOperation(AuditAction.CREATE, 'application', undefined, async () => {
|
|
1129
|
-
return postOne(
|
|
1069
|
+
return postOne(ENDPOINTS.applications, input);
|
|
1130
1070
|
});
|
|
1131
1071
|
}
|
|
1132
1072
|
/**
|
|
1133
1073
|
* Update an application
|
|
1134
1074
|
*/
|
|
1135
1075
|
export async function updateApplication(id, input) {
|
|
1136
|
-
|
|
1137
|
-
throw new Error('Invalid application ID. Please provide a positive number.');
|
|
1138
|
-
}
|
|
1076
|
+
validateId(id, 'application');
|
|
1139
1077
|
return auditedOperation(AuditAction.UPDATE, 'application', id, async () => {
|
|
1140
|
-
return patchOne(
|
|
1078
|
+
return patchOne(endpointWithId(ENDPOINTS.applications, id), input);
|
|
1141
1079
|
});
|
|
1142
1080
|
}
|
|
1143
1081
|
/**
|
|
1144
1082
|
* Delete an application
|
|
1145
1083
|
*/
|
|
1146
1084
|
export async function deleteApplication(id) {
|
|
1147
|
-
|
|
1148
|
-
throw new Error('Invalid application ID. Please provide a positive number.');
|
|
1149
|
-
}
|
|
1085
|
+
validateId(id, 'application');
|
|
1150
1086
|
return auditedOperation(AuditAction.DELETE, 'application', id, async () => {
|
|
1151
|
-
await deleteOne(
|
|
1087
|
+
await deleteOne(endpointWithId(ENDPOINTS.applications, id));
|
|
1152
1088
|
});
|
|
1153
1089
|
}
|
|
1154
1090
|
/**
|
|
1155
1091
|
* Advance an application to the next stage
|
|
1156
1092
|
*/
|
|
1157
1093
|
export async function advanceApplication(id) {
|
|
1158
|
-
|
|
1159
|
-
throw new Error('Invalid application ID. Please provide a positive number.');
|
|
1160
|
-
}
|
|
1094
|
+
validateId(id, 'application');
|
|
1161
1095
|
return auditedOperation(AuditAction.UPDATE, 'application', id, async () => {
|
|
1162
|
-
return postAction(
|
|
1096
|
+
return postAction(endpointWithAction(ENDPOINTS.applications, id, 'apply'));
|
|
1163
1097
|
});
|
|
1164
1098
|
}
|
|
1165
1099
|
// ============================================================================
|
|
@@ -1173,7 +1107,7 @@ export async function listPayrollSupplements(employeeId, options) {
|
|
|
1173
1107
|
const queryParams = {};
|
|
1174
1108
|
if (employeeId)
|
|
1175
1109
|
queryParams.employee_id = employeeId;
|
|
1176
|
-
const supplements = await fetchList(
|
|
1110
|
+
const supplements = await fetchList(ENDPOINTS.payrollSupplements, {
|
|
1177
1111
|
params: queryParams,
|
|
1178
1112
|
});
|
|
1179
1113
|
return sliceForPagination(supplements, params);
|
|
@@ -1182,10 +1116,8 @@ export async function listPayrollSupplements(employeeId, options) {
|
|
|
1182
1116
|
* Get a specific payroll supplement by ID
|
|
1183
1117
|
*/
|
|
1184
1118
|
export async function getPayrollSupplement(id) {
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
}
|
|
1188
|
-
return fetchOne(`/payroll/supplements/${id}`);
|
|
1119
|
+
validateId(id, 'supplement');
|
|
1120
|
+
return fetchOne(endpointWithId(ENDPOINTS.payrollSupplements, id));
|
|
1189
1121
|
}
|
|
1190
1122
|
/**
|
|
1191
1123
|
* List tax identifiers
|
|
@@ -1195,7 +1127,7 @@ export async function listTaxIdentifiers(employeeId, options) {
|
|
|
1195
1127
|
const queryParams = {};
|
|
1196
1128
|
if (employeeId)
|
|
1197
1129
|
queryParams.employee_id = employeeId;
|
|
1198
|
-
const identifiers = await fetchList(
|
|
1130
|
+
const identifiers = await fetchList(ENDPOINTS.taxIdentifiers, {
|
|
1199
1131
|
params: queryParams,
|
|
1200
1132
|
});
|
|
1201
1133
|
return sliceForPagination(identifiers, params);
|
|
@@ -1204,10 +1136,8 @@ export async function listTaxIdentifiers(employeeId, options) {
|
|
|
1204
1136
|
* Get a specific tax identifier by ID
|
|
1205
1137
|
*/
|
|
1206
1138
|
export async function getTaxIdentifier(id) {
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
}
|
|
1210
|
-
return fetchOne(`/payroll_employees/identifiers/${id}`);
|
|
1139
|
+
validateId(id, 'tax identifier');
|
|
1140
|
+
return fetchOne(endpointWithId(ENDPOINTS.taxIdentifiers, id));
|
|
1211
1141
|
}
|
|
1212
1142
|
/**
|
|
1213
1143
|
* List family situations
|
|
@@ -1217,7 +1147,7 @@ export async function listFamilySituations(employeeId, options) {
|
|
|
1217
1147
|
const queryParams = {};
|
|
1218
1148
|
if (employeeId)
|
|
1219
1149
|
queryParams.employee_id = employeeId;
|
|
1220
|
-
const situations = await fetchList(
|
|
1150
|
+
const situations = await fetchList(ENDPOINTS.familySituations, {
|
|
1221
1151
|
params: queryParams,
|
|
1222
1152
|
});
|
|
1223
1153
|
return sliceForPagination(situations, params);
|
|
@@ -1226,9 +1156,7 @@ export async function listFamilySituations(employeeId, options) {
|
|
|
1226
1156
|
* Get a specific family situation by ID
|
|
1227
1157
|
*/
|
|
1228
1158
|
export async function getFamilySituation(id) {
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
}
|
|
1232
|
-
return fetchOne(`/payroll/family_situations/${id}`);
|
|
1159
|
+
validateId(id, 'family situation');
|
|
1160
|
+
return fetchOne(endpointWithId(ENDPOINTS.familySituations, id));
|
|
1233
1161
|
}
|
|
1234
1162
|
//# sourceMappingURL=api.js.map
|