@markwharton/eh-payroll 2.2.0 → 2.4.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 +35 -1
- package/dist/client.d.ts +17 -1
- package/dist/client.js +95 -25
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2 -1
- package/dist/types.d.ts +69 -0
- package/dist/types.js +25 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,6 +43,14 @@ const pubResult = await client.getRosterShifts('2026-02-03', '2026-02-09', {
|
|
|
43
43
|
});
|
|
44
44
|
if (pubResult.ok) console.log(pubResult.data); // EHRosterShift[]
|
|
45
45
|
|
|
46
|
+
// Get leave requests for a date range (all filters server-side)
|
|
47
|
+
const leaveResult = await client.getLeaveRequests({
|
|
48
|
+
fromDate: '2026-01-01',
|
|
49
|
+
toDate: '2026-03-31',
|
|
50
|
+
status: 'Approved',
|
|
51
|
+
});
|
|
52
|
+
if (leaveResult.ok) console.log(leaveResult.data); // EHLeaveRequest[]
|
|
53
|
+
|
|
46
54
|
// Get business locations
|
|
47
55
|
const locResult = await client.getLocations();
|
|
48
56
|
if (locResult.ok) console.log(locResult.data); // EHLocation[]
|
|
@@ -110,15 +118,39 @@ const employees = result.data;
|
|
|
110
118
|
| `getKiosks()` | — | `Result<EHKiosk[]>` |
|
|
111
119
|
| `getKioskStaff(kioskId, options?)` | `number, EHKioskStaffOptions?` | `Result<EHKioskEmployee[]>` |
|
|
112
120
|
| `getReportFields()` | — | `Result<EHReportField[]>` |
|
|
121
|
+
| `getLeaveRequests(options?)` | `EHLeaveRequestOptions?` | `Result<EHLeaveRequest[]>` |
|
|
113
122
|
| `getEmployeeDetailsReport(options?)` | `EHEmployeeDetailsReportOptions?` | `Result<Record<string, unknown>[]>` |
|
|
114
123
|
|
|
124
|
+
### `getLeaveRequests()`
|
|
125
|
+
|
|
126
|
+
Returns leave requests with all filters applied server-side. The business-level endpoint (`/api/v2/business/{businessId}/leaverequest`) returns a flat array — no pagination is available.
|
|
127
|
+
|
|
128
|
+
**Leave requests are time-series data** — unlike employees and locations which remain relatively stable, leave requests grow continuously as new requests accumulate. Always use `fromDate`/`toDate` filters to bound the result set. Without date filters, the API returns the entire leave request history.
|
|
129
|
+
|
|
130
|
+
> **Note:** The Payroll API also provides a per-employee endpoint (`/api/v2/business/{businessId}/employee/{employeeId}/leaverequest`) with OData support (`$filter`, `$orderby`, `$top`, `$skip`). This client currently uses only the business-level endpoint.
|
|
131
|
+
|
|
132
|
+
**`EHLeaveRequestOptions`:**
|
|
133
|
+
|
|
134
|
+
| Option | Type | Description |
|
|
135
|
+
|--------|------|-------------|
|
|
136
|
+
| `fromDate` | `string` | Start date filter (YYYY-MM-DD) |
|
|
137
|
+
| `toDate` | `string` | End date filter (YYYY-MM-DD) |
|
|
138
|
+
| `status` | `EHLeaveRequestStatus` | `'Approved'`, `'Pending'`, `'Rejected'`, or `'Cancelled'` |
|
|
139
|
+
| `employeeId` | `number` | Filter by employee ID |
|
|
140
|
+
| `leaveCategoryId` | `number` | Filter by leave category ID |
|
|
141
|
+
| `locationId` | `number` | Filter by location ID |
|
|
142
|
+
|
|
143
|
+
### `getEmployeeDetailsReport()`
|
|
144
|
+
|
|
145
|
+
Returns all employees with the requested columns in a single API call. The response is dynamic — field keys depend on `selectedColumns`. Results are cached with `employeeDetailsReportTtl` (default: 2 min).
|
|
146
|
+
|
|
115
147
|
### `getRosterShifts()`
|
|
116
148
|
|
|
117
149
|
Automatically paginates through all results (100 per page). Returns the complete set of roster shifts for the requested date range. All filter options are applied server-side, reducing the number of results and pages fetched.
|
|
118
150
|
|
|
119
151
|
### Query Parameter Casing
|
|
120
152
|
|
|
121
|
-
The [KeyPay Swagger spec](https://api.keypay.com.au/swagger-au.json) uses inconsistent query parameter casing across endpoints. Roster shifts use PascalCase (`EmployeeId`, `ShiftStatus`), while
|
|
153
|
+
The [KeyPay Swagger spec](https://api.keypay.com.au/swagger-au.json) uses inconsistent query parameter casing across endpoints. Roster shifts and leave requests use PascalCase (`EmployeeId`, `ShiftStatus`, `FromDate`), while other endpoints use camelCase (`selectedColumns`, `filter.locationId`). The library accepts camelCase options throughout and converts to PascalCase internally where needed.
|
|
122
154
|
|
|
123
155
|
## Configuration
|
|
124
156
|
|
|
@@ -151,9 +183,11 @@ const client = new EHClient({
|
|
|
151
183
|
| Employee groups | 5 min |
|
|
152
184
|
| Standard hours | 5 min |
|
|
153
185
|
| Roster shifts | 2 min |
|
|
186
|
+
| Leave requests | 2 min |
|
|
154
187
|
| Kiosks | 5 min |
|
|
155
188
|
| Kiosk staff | 1 min |
|
|
156
189
|
| Report fields | 10 min |
|
|
190
|
+
| Employee details report | 2 min |
|
|
157
191
|
|
|
158
192
|
Failed API results (`ok: false`) are never cached — transient errors won't persist for the full TTL. See the [root README Cache System section](../../README.md#cache-system) for the full cache architecture (layered stores, PII handling, request coalescing).
|
|
159
193
|
|
package/dist/client.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @see https://api.keypay.com.au/
|
|
8
8
|
*/
|
|
9
|
-
import type { EHConfig, EHEmployeeOptions, EHSingleEmployeeOptions, EHStandardHours, EHLocation, EHEmployeeGroup, EHRosterShift, EHRosterShiftOptions, EHKiosk, EHKioskEmployee, EHKioskStaffOptions, EHReportField, EHEmployeeDetailsReportOptions } from './types.js';
|
|
9
|
+
import type { EHConfig, EHLeaveRequest, EHLeaveRequestOptions, EHEmployeeOptions, EHSingleEmployeeOptions, EHStandardHours, EHLocation, EHEmployeeGroup, EHRosterShift, EHRosterShiftOptions, EHKiosk, EHKioskEmployee, EHKioskStaffOptions, EHReportField, EHEmployeeDetailsReportOptions } from './types.js';
|
|
10
10
|
import type { EHAuEmployee } from './employee-types.generated.js';
|
|
11
11
|
import type { Result } from '@markwharton/api-core';
|
|
12
12
|
/**
|
|
@@ -32,7 +32,10 @@ export declare class EHClient {
|
|
|
32
32
|
private readonly cacheTtl;
|
|
33
33
|
private readonly retryConfig?;
|
|
34
34
|
private readonly rateLimiter?;
|
|
35
|
+
private readonly persistRestricted;
|
|
35
36
|
constructor(config: EHConfig);
|
|
37
|
+
/** Cache options for restricted-tier methods: skip persistent stores when persistRestricted is false. */
|
|
38
|
+
private get restrictedPersistOpt();
|
|
36
39
|
/**
|
|
37
40
|
* Route through cache if enabled, otherwise call factory directly.
|
|
38
41
|
* Failed Results (ok === false) are never cached — transient errors
|
|
@@ -43,6 +46,10 @@ export declare class EHClient {
|
|
|
43
46
|
* Clear all cached API responses.
|
|
44
47
|
*/
|
|
45
48
|
clearCache(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Build a URL for a business-scoped endpoint.
|
|
51
|
+
*/
|
|
52
|
+
private businessUrl;
|
|
46
53
|
/**
|
|
47
54
|
* Make an authenticated request to the EH API
|
|
48
55
|
*
|
|
@@ -70,6 +77,15 @@ export declare class EHClient {
|
|
|
70
77
|
* Validate the API key by calling GET /user
|
|
71
78
|
*/
|
|
72
79
|
validateApiKey(): Promise<Result<void>>;
|
|
80
|
+
/**
|
|
81
|
+
* Get leave requests (server-side filtering)
|
|
82
|
+
*
|
|
83
|
+
* All filter options are passed as query parameters to the API.
|
|
84
|
+
* The endpoint returns a flat array (not paginated).
|
|
85
|
+
*
|
|
86
|
+
* @see https://api.keypay.com.au/australia/reference/leave-requests/au-business-hours-leave-request--list-leave-requests.html
|
|
87
|
+
*/
|
|
88
|
+
getLeaveRequests(options?: EHLeaveRequestOptions): Promise<Result<EHLeaveRequest[]>>;
|
|
73
89
|
/**
|
|
74
90
|
* Get all employees (unstructured format)
|
|
75
91
|
*/
|
package/dist/client.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @see https://api.keypay.com.au/
|
|
8
8
|
*/
|
|
9
|
-
import { AU_EMPLOYEE_OPERATIONAL_FIELDS, AU_EMPLOYEE_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
|
|
9
|
+
import { AU_EMPLOYEE_OPERATIONAL_FIELDS, AU_EMPLOYEE_FIELDS, LEAVE_REQUEST_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
|
|
10
10
|
import { buildBasicAuthHeader } from './utils.js';
|
|
11
11
|
import { parseEHPayrollErrorResponse } from './errors.js';
|
|
12
12
|
import { EH_API_BASE, EH_REGION_URLS } from './constants.js';
|
|
@@ -42,6 +42,7 @@ export class EHClient {
|
|
|
42
42
|
}
|
|
43
43
|
this.cacheTtl = {
|
|
44
44
|
employeesTtl: config.cache?.employeesTtl ?? 300000,
|
|
45
|
+
leaveRequestsTtl: config.cache?.leaveRequestsTtl ?? 120000,
|
|
45
46
|
locationsTtl: config.cache?.locationsTtl ?? 300000,
|
|
46
47
|
groupsTtl: config.cache?.groupsTtl ?? 300000,
|
|
47
48
|
standardHoursTtl: config.cache?.standardHoursTtl ?? 300000,
|
|
@@ -49,6 +50,7 @@ export class EHClient {
|
|
|
49
50
|
kiosksTtl: config.cache?.kiosksTtl ?? 300000,
|
|
50
51
|
kioskStaffTtl: config.cache?.kioskStaffTtl ?? 60000,
|
|
51
52
|
reportFieldsTtl: config.cache?.reportFieldsTtl ?? 600000,
|
|
53
|
+
employeeDetailsReportTtl: config.cache?.employeeDetailsReportTtl ?? 120000,
|
|
52
54
|
};
|
|
53
55
|
// Initialize retry config with defaults if provided
|
|
54
56
|
this.retryConfig = resolveRetryConfig(config.retry);
|
|
@@ -57,6 +59,11 @@ export class EHClient {
|
|
|
57
59
|
if (rateLimitPerSecond > 0) {
|
|
58
60
|
this.rateLimiter = new RateLimiter(rateLimitPerSecond);
|
|
59
61
|
}
|
|
62
|
+
this.persistRestricted = config.persistRestricted ?? true;
|
|
63
|
+
}
|
|
64
|
+
/** Cache options for restricted-tier methods: skip persistent stores when persistRestricted is false. */
|
|
65
|
+
get restrictedPersistOpt() {
|
|
66
|
+
return this.persistRestricted ? undefined : { persist: false };
|
|
60
67
|
}
|
|
61
68
|
/**
|
|
62
69
|
* Route through cache if enabled, otherwise call factory directly.
|
|
@@ -77,6 +84,14 @@ export class EHClient {
|
|
|
77
84
|
clearCache() {
|
|
78
85
|
this.cache?.clear();
|
|
79
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Build a URL for a business-scoped endpoint.
|
|
89
|
+
*/
|
|
90
|
+
businessUrl(path, params) {
|
|
91
|
+
const base = `${this.baseUrl}/business/${this.businessId}/${path}`;
|
|
92
|
+
const qs = params?.toString();
|
|
93
|
+
return qs ? `${base}?${qs}` : base;
|
|
94
|
+
}
|
|
80
95
|
/**
|
|
81
96
|
* Make an authenticated request to the EH API
|
|
82
97
|
*
|
|
@@ -186,6 +201,53 @@ export class EHClient {
|
|
|
186
201
|
}
|
|
187
202
|
}
|
|
188
203
|
// ============================================================================
|
|
204
|
+
// Leave Requests
|
|
205
|
+
// ============================================================================
|
|
206
|
+
/**
|
|
207
|
+
* Get leave requests (server-side filtering)
|
|
208
|
+
*
|
|
209
|
+
* All filter options are passed as query parameters to the API.
|
|
210
|
+
* The endpoint returns a flat array (not paginated).
|
|
211
|
+
*
|
|
212
|
+
* @see https://api.keypay.com.au/australia/reference/leave-requests/au-business-hours-leave-request--list-leave-requests.html
|
|
213
|
+
*/
|
|
214
|
+
async getLeaveRequests(options) {
|
|
215
|
+
const parts = ['leaverequests'];
|
|
216
|
+
if (options?.fromDate)
|
|
217
|
+
parts.push(`from:${options.fromDate}`);
|
|
218
|
+
if (options?.toDate)
|
|
219
|
+
parts.push(`to:${options.toDate}`);
|
|
220
|
+
if (options?.status)
|
|
221
|
+
parts.push(`s:${options.status}`);
|
|
222
|
+
if (options?.employeeId != null)
|
|
223
|
+
parts.push(`eid:${options.employeeId}`);
|
|
224
|
+
if (options?.leaveCategoryId != null)
|
|
225
|
+
parts.push(`lcid:${options.leaveCategoryId}`);
|
|
226
|
+
if (options?.locationId != null)
|
|
227
|
+
parts.push(`lid:${options.locationId}`);
|
|
228
|
+
const cacheKey = parts.join(':');
|
|
229
|
+
return this.cached(cacheKey, this.cacheTtl.leaveRequestsTtl, async () => {
|
|
230
|
+
const params = new URLSearchParams();
|
|
231
|
+
if (options?.fromDate)
|
|
232
|
+
params.set('FromDate', options.fromDate);
|
|
233
|
+
if (options?.toDate)
|
|
234
|
+
params.set('ToDate', options.toDate);
|
|
235
|
+
if (options?.status)
|
|
236
|
+
params.set('Status', options.status);
|
|
237
|
+
if (options?.employeeId != null)
|
|
238
|
+
params.set('EmployeeId', String(options.employeeId));
|
|
239
|
+
if (options?.leaveCategoryId != null)
|
|
240
|
+
params.set('LeaveCategoryId', String(options.leaveCategoryId));
|
|
241
|
+
if (options?.locationId != null)
|
|
242
|
+
params.set('LocationId', String(options.locationId));
|
|
243
|
+
const url = this.businessUrl('leaverequest', params);
|
|
244
|
+
return this.fetchAndParse(url, async (r) => {
|
|
245
|
+
return (await r.json())
|
|
246
|
+
.map(item => pickFields(item, LEAVE_REQUEST_FIELDS));
|
|
247
|
+
});
|
|
248
|
+
}, this.restrictedPersistOpt);
|
|
249
|
+
}
|
|
250
|
+
// ============================================================================
|
|
189
251
|
// Employees
|
|
190
252
|
// ============================================================================
|
|
191
253
|
/**
|
|
@@ -201,7 +263,7 @@ export class EHClient {
|
|
|
201
263
|
if (options?.includePii)
|
|
202
264
|
parts.push('pii');
|
|
203
265
|
const cacheKey = parts.join(':');
|
|
204
|
-
const persistOpt = options?.includePii ? { persist: false } : undefined;
|
|
266
|
+
const persistOpt = (options?.includePii || !this.persistRestricted) ? { persist: false } : undefined;
|
|
205
267
|
return this.cached(cacheKey, this.cacheTtl.employeesTtl, () => {
|
|
206
268
|
const params = new URLSearchParams();
|
|
207
269
|
if (options?.payScheduleId != null)
|
|
@@ -221,7 +283,7 @@ export class EHClient {
|
|
|
221
283
|
async getEmployee(employeeId, options) {
|
|
222
284
|
const fields = options?.includePii ? AU_EMPLOYEE_FIELDS : AU_EMPLOYEE_OPERATIONAL_FIELDS;
|
|
223
285
|
const cacheKey = options?.includePii ? `employee:${employeeId}:pii` : `employee:${employeeId}`;
|
|
224
|
-
const persistOpt = options?.includePii ? { persist: false } : undefined;
|
|
286
|
+
const persistOpt = (options?.includePii || !this.persistRestricted) ? { persist: false } : undefined;
|
|
225
287
|
return this.cached(cacheKey, this.cacheTtl.employeesTtl, async () => {
|
|
226
288
|
const url = `${this.baseUrl}/business/${this.businessId}/employee/unstructured/${employeeId}`;
|
|
227
289
|
return this.fetchAndParse(url, async (r) => {
|
|
@@ -241,7 +303,7 @@ export class EHClient {
|
|
|
241
303
|
return this.fetchAndParse(url, async (r) => {
|
|
242
304
|
return await r.json();
|
|
243
305
|
}, { description: `Get standard hours for employee ${employeeId}` });
|
|
244
|
-
});
|
|
306
|
+
}, this.restrictedPersistOpt);
|
|
245
307
|
}
|
|
246
308
|
// ============================================================================
|
|
247
309
|
// Locations
|
|
@@ -386,10 +448,7 @@ export class EHClient {
|
|
|
386
448
|
if (options?.restrictCurrentShiftsToCurrentKioskLocation) {
|
|
387
449
|
params.set('restrictCurrentShiftsToCurrentKioskLocation', 'true');
|
|
388
450
|
}
|
|
389
|
-
const
|
|
390
|
-
const url = queryString
|
|
391
|
-
? `${this.baseUrl}/business/${this.businessId}/kiosk/${kioskId}/staff?${queryString}`
|
|
392
|
-
: `${this.baseUrl}/business/${this.businessId}/kiosk/${kioskId}/staff`;
|
|
451
|
+
const url = this.businessUrl(`kiosk/${kioskId}/staff`, params);
|
|
393
452
|
return this.fetchAndParse(url, async (r) => {
|
|
394
453
|
return (await r.json())
|
|
395
454
|
.map(item => pickFields(item, KIOSK_EMPLOYEE_FIELDS));
|
|
@@ -420,26 +479,37 @@ export class EHClient {
|
|
|
420
479
|
* The response is dynamic (JObject[]) — field keys depend on selectedColumns.
|
|
421
480
|
*/
|
|
422
481
|
async getEmployeeDetailsReport(options) {
|
|
423
|
-
const
|
|
424
|
-
if (options?.selectedColumns)
|
|
425
|
-
|
|
426
|
-
params.append('selectedColumns', col);
|
|
427
|
-
}
|
|
428
|
-
}
|
|
482
|
+
const parts = ['report:employeedetails'];
|
|
483
|
+
if (options?.selectedColumns?.length)
|
|
484
|
+
parts.push(`cols:${options.selectedColumns.join(',')}`);
|
|
429
485
|
if (options?.locationId != null)
|
|
430
|
-
|
|
486
|
+
parts.push(`loc:${options.locationId}`);
|
|
431
487
|
if (options?.employingEntityId != null)
|
|
432
|
-
|
|
488
|
+
parts.push(`ee:${options.employingEntityId}`);
|
|
433
489
|
if (options?.includeActive != null)
|
|
434
|
-
|
|
490
|
+
parts.push(`a:${options.includeActive}`);
|
|
435
491
|
if (options?.includeInactive != null)
|
|
436
|
-
|
|
437
|
-
const
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
492
|
+
parts.push(`i:${options.includeInactive}`);
|
|
493
|
+
const cacheKey = parts.join(':');
|
|
494
|
+
return this.cached(cacheKey, this.cacheTtl.employeeDetailsReportTtl, async () => {
|
|
495
|
+
const params = new URLSearchParams();
|
|
496
|
+
if (options?.selectedColumns) {
|
|
497
|
+
for (const col of options.selectedColumns) {
|
|
498
|
+
params.append('selectedColumns', col);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
if (options?.locationId != null)
|
|
502
|
+
params.set('locationId', String(options.locationId));
|
|
503
|
+
if (options?.employingEntityId != null)
|
|
504
|
+
params.set('employingEntityId', String(options.employingEntityId));
|
|
505
|
+
if (options?.includeActive != null)
|
|
506
|
+
params.set('includeActive', String(options.includeActive));
|
|
507
|
+
if (options?.includeInactive != null)
|
|
508
|
+
params.set('includeInactive', String(options.includeInactive));
|
|
509
|
+
const url = this.businessUrl('report/employeedetails', params);
|
|
510
|
+
return this.fetchAndParse(url, async (r) => {
|
|
511
|
+
return await r.json();
|
|
512
|
+
});
|
|
513
|
+
}, this.restrictedPersistOpt);
|
|
444
514
|
}
|
|
445
515
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -20,8 +20,10 @@
|
|
|
20
20
|
* ```
|
|
21
21
|
*/
|
|
22
22
|
export { EHClient } from './client.js';
|
|
23
|
-
export type { EHConfig, EHCacheConfig, EHRetryConfig, EHEmployee, EHEmployeeOptions, EHSingleEmployeeOptions, EHStandardHours, EHLocation, EHEmployeeGroup, EHRosterShift, EHRosterShiftOptions, EHAttendanceStatus, EHKiosk, EHKioskEmployee, EHKioskStaffOptions, EHReportField, EHEmployeeDetailsReportOptions, } from './types.js';
|
|
24
|
-
export { AU_EMPLOYEE_OPERATIONAL_FIELDS, AU_EMPLOYEE_PII_FIELDS, AU_EMPLOYEE_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
|
|
23
|
+
export type { EHConfig, EHCacheConfig, EHRetryConfig, EHLeaveRequest, EHLeaveRequestOptions, EHLeaveRequestStatus, EHEmployee, EHEmployeeOptions, EHSingleEmployeeOptions, EHStandardHours, EHLocation, EHEmployeeGroup, EHRosterShift, EHRosterShiftOptions, EHAttendanceStatus, EHKiosk, EHKioskEmployee, EHKioskStaffOptions, EHReportField, EHEmployeeDetailsReportOptions, } from './types.js';
|
|
24
|
+
export { AU_EMPLOYEE_OPERATIONAL_FIELDS, AU_EMPLOYEE_PII_FIELDS, AU_EMPLOYEE_FIELDS, LEAVE_REQUEST_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
|
|
25
|
+
export type { AccessTier } from './types.js';
|
|
26
|
+
export { METHOD_TIERS } from './types.js';
|
|
25
27
|
export type { EHAuEmployee } from './employee-types.generated.js';
|
|
26
28
|
export { buildBasicAuthHeader } from './utils.js';
|
|
27
29
|
export { ok, err, getErrorMessage, pickFields, RateLimiter, TTLCache, MemoryCacheStore, LayeredCache } from '@markwharton/api-core';
|
package/dist/index.js
CHANGED
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
// Main client
|
|
23
23
|
export { EHClient } from './client.js';
|
|
24
24
|
// Field key constants (whitelists for pickFields)
|
|
25
|
-
export { AU_EMPLOYEE_OPERATIONAL_FIELDS, AU_EMPLOYEE_PII_FIELDS, AU_EMPLOYEE_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
|
|
25
|
+
export { AU_EMPLOYEE_OPERATIONAL_FIELDS, AU_EMPLOYEE_PII_FIELDS, AU_EMPLOYEE_FIELDS, LEAVE_REQUEST_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
|
|
26
|
+
export { METHOD_TIERS } from './types.js';
|
|
26
27
|
// Utilities
|
|
27
28
|
export { buildBasicAuthHeader } from './utils.js';
|
|
28
29
|
// Re-exported from @markwharton/api-core
|
package/dist/types.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ import type { RetryConfig, ClientConfig } from '@markwharton/api-core';
|
|
|
15
15
|
export interface EHCacheConfig {
|
|
16
16
|
/** TTL for employee list (default: 300000 = 5 min) */
|
|
17
17
|
employeesTtl?: number;
|
|
18
|
+
/** TTL for leave requests (default: 120000 = 2 min) */
|
|
19
|
+
leaveRequestsTtl?: number;
|
|
18
20
|
/** TTL for locations (default: 300000 = 5 min) */
|
|
19
21
|
locationsTtl?: number;
|
|
20
22
|
/** TTL for employee groups (default: 300000 = 5 min) */
|
|
@@ -29,6 +31,8 @@ export interface EHCacheConfig {
|
|
|
29
31
|
kioskStaffTtl?: number;
|
|
30
32
|
/** TTL for report fields (default: 600000 = 10 min) */
|
|
31
33
|
reportFieldsTtl?: number;
|
|
34
|
+
/** TTL for employee details report (default: 120000 = 2 min) */
|
|
35
|
+
employeeDetailsReportTtl?: number;
|
|
32
36
|
}
|
|
33
37
|
/** @deprecated Use `RetryConfig` from `@markwharton/api-core` directly. */
|
|
34
38
|
export type EHRetryConfig = RetryConfig;
|
|
@@ -46,6 +50,8 @@ export interface EHConfig extends ClientConfig {
|
|
|
46
50
|
cache?: EHCacheConfig;
|
|
47
51
|
/** Max requests per second (default: 5 per API spec). Set 0 to disable. */
|
|
48
52
|
rateLimitPerSecond?: number;
|
|
53
|
+
/** Whether to persist restricted-tier data in persistent cache stores (default: true). Set false to keep restricted data in memory only. */
|
|
54
|
+
persistRestricted?: boolean;
|
|
49
55
|
}
|
|
50
56
|
/**
|
|
51
57
|
* Employee from unstructured endpoint
|
|
@@ -172,6 +178,57 @@ export interface EHKioskEmployee {
|
|
|
172
178
|
/** Last recorded time in UTC */
|
|
173
179
|
recordedTimeUtc: string | null;
|
|
174
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Leave request from the Payroll API
|
|
183
|
+
*
|
|
184
|
+
* From GET /business/{id}/leaverequest
|
|
185
|
+
* Field whitelist from Swagger HourLeaveRequestResponseModel.
|
|
186
|
+
*/
|
|
187
|
+
export interface EHLeaveRequest {
|
|
188
|
+
/** Leave request ID */
|
|
189
|
+
id: number;
|
|
190
|
+
/** Employee ID */
|
|
191
|
+
employeeId: number;
|
|
192
|
+
/** Leave category ID */
|
|
193
|
+
leaveCategoryId: number;
|
|
194
|
+
/** Employee display name */
|
|
195
|
+
employee: string;
|
|
196
|
+
/** Leave category name */
|
|
197
|
+
leaveCategory: string;
|
|
198
|
+
/** Start date (ISO 8601 datetime) */
|
|
199
|
+
fromDate: string;
|
|
200
|
+
/** End date (ISO 8601 datetime) */
|
|
201
|
+
toDate: string;
|
|
202
|
+
/** Total hours requested */
|
|
203
|
+
totalHours: number;
|
|
204
|
+
/** Hours actually applied */
|
|
205
|
+
hoursApplied: number;
|
|
206
|
+
/** Notes on the leave request */
|
|
207
|
+
notes: string | null;
|
|
208
|
+
/** Status: Approved, Pending, Rejected, Cancelled */
|
|
209
|
+
status: string;
|
|
210
|
+
}
|
|
211
|
+
/** Leave request status values */
|
|
212
|
+
export type EHLeaveRequestStatus = 'Approved' | 'Pending' | 'Rejected' | 'Cancelled';
|
|
213
|
+
/**
|
|
214
|
+
* Options for getLeaveRequests
|
|
215
|
+
*
|
|
216
|
+
* All filters are passed server-side to the API.
|
|
217
|
+
*/
|
|
218
|
+
export interface EHLeaveRequestOptions {
|
|
219
|
+
/** Filter by start date (ISO 8601 date-time → API FromDate) */
|
|
220
|
+
fromDate?: string;
|
|
221
|
+
/** Filter by end date (ISO 8601 date-time → API ToDate) */
|
|
222
|
+
toDate?: string;
|
|
223
|
+
/** Filter by status (→ API Status) */
|
|
224
|
+
status?: EHLeaveRequestStatus;
|
|
225
|
+
/** Filter by employee ID (→ API EmployeeId) */
|
|
226
|
+
employeeId?: number;
|
|
227
|
+
/** Filter by leave category ID (→ API LeaveCategoryId) */
|
|
228
|
+
leaveCategoryId?: number;
|
|
229
|
+
/** Filter by location ID (→ API LocationId) */
|
|
230
|
+
locationId?: number;
|
|
231
|
+
}
|
|
175
232
|
/**
|
|
176
233
|
* Options for getEmployees
|
|
177
234
|
*/
|
|
@@ -291,6 +348,8 @@ export interface EHEmployeeDetailsReportOptions {
|
|
|
291
348
|
/** Include inactive employees (default: false) */
|
|
292
349
|
includeInactive?: boolean;
|
|
293
350
|
}
|
|
351
|
+
/** Whitelisted fields for EHLeaveRequest */
|
|
352
|
+
export declare const LEAVE_REQUEST_FIELDS: readonly ["id", "employeeId", "leaveCategoryId", "employee", "leaveCategory", "fromDate", "toDate", "totalHours", "hoursApplied", "notes", "status"];
|
|
294
353
|
/** Whitelisted fields for EHLocation */
|
|
295
354
|
export declare const LOCATION_FIELDS: readonly ["id", "parentId", "name", "externalId", "source", "fullyQualifiedName", "isGlobal", "state", "country"];
|
|
296
355
|
/** Whitelisted fields for EHKiosk */
|
|
@@ -313,3 +372,13 @@ export declare const AU_EMPLOYEE_OPERATIONAL_FIELDS: readonly ["id", "externalId
|
|
|
313
372
|
export declare const AU_EMPLOYEE_PII_FIELDS: readonly ["dateOfBirth", "gender", "title", "middleName", "preferredName", "previousSurname", "emailAddress", "homePhone", "mobilePhone", "workPhone", "bankAccount1_AccountName", "bankAccount1_AccountNumber", "bankAccount1_AllocatedPercentage", "bankAccount1_BSB", "bankAccount1_FixedAmount", "bankAccount2_AccountName", "bankAccount2_AccountNumber", "bankAccount2_AllocatedPercentage", "bankAccount2_BSB", "bankAccount2_FixedAmount", "bankAccount3_AccountName", "bankAccount3_AccountNumber", "bankAccount3_AllocatedPercentage", "bankAccount3_BSB", "bankAccount3_FixedAmount", "emergencyContact1_Address", "emergencyContact1_AlternateContactNumber", "emergencyContact1_ContactNumber", "emergencyContact1_Name", "emergencyContact1_Relationship", "emergencyContact2_Address", "emergencyContact2_AlternateContactNumber", "emergencyContact2_ContactNumber", "emergencyContact2_Name", "emergencyContact2_Relationship", "postalStreetAddress", "postalAddressLine2", "postalPostCode", "postalCountry", "postalState", "postalSuburb", "postalAddressIsOverseas", "residentialStreetAddress", "residentialAddressLine2", "residentialPostCode", "residentialCountry", "residentialState", "residentialSuburb", "residentialAddressIsOverseas", "taxFileNumber", "taxCategory", "taxVariation", "claimTaxFreeThreshold", "claimMedicareLevyReduction", "medicareLevyExemption", "medicareLevyReductionDependentCount", "medicareLevyReductionSpouse", "medicareLevySurchargeWithholdingTier", "seniorsTaxOffset", "otherTaxOffset", "stslDebt", "hasWithholdingVariation", "dateTaxFileDeclarationReported", "dateTaxFileDeclarationSigned", "superFund1_AllocatedPercentage", "superFund1_EmployerNominatedFund", "superFund1_FixedAmount", "superFund1_FundName", "superFund1_MemberNumber", "superFund1_ProductCode", "superFund2_AllocatedPercentage", "superFund2_EmployerNominatedFund", "superFund2_FixedAmount", "superFund2_FundName", "superFund2_MemberNumber", "superFund2_ProductCode", "superFund3_AllocatedPercentage", "superFund3_EmployerNominatedFund", "superFund3_FixedAmount", "superFund3_FundName", "superFund3_MemberNumber", "superFund3_ProductCode", "contractorABN", "employingEntityABN", "hasApprovedWorkingHolidayVisa", "workingHolidayVisaCountry", "workingHolidayVisaStartDate"];
|
|
314
373
|
/** All whitelisted fields for EHAuEmployee (operational + PII) */
|
|
315
374
|
export declare const AU_EMPLOYEE_FIELDS: readonly ["id", "externalId", "firstName", "surname", "status", "startDate", "endDate", "anniversaryDate", "dateCreated", "employmentType", "jobTitle", "employmentAgreement", "employmentAgreementId", "paySchedule", "payRateTemplate", "rate", "rateUnit", "hoursPerWeek", "hoursPerDay", "primaryPayCategory", "payConditionRuleSet", "overrideTemplateRate", "automaticallyPayEmployee", "primaryLocation", "locations", "tags", "workTypes", "reportingDimensionValues", "leaveAccrualStartDateType", "leaveTemplate", "leaveYearStart", "isEnabledForTimesheets", "rosteringNotificationChoices", "paySlipNotificationType", "terminationReason", "australianResident", "awardId", "businessAwardPackage", "automaticallyApplyPublicHolidayNotWorkedEarningsLines", "closelyHeldEmployee", "closelyHeldReporting", "disableAutoProgression", "dvlPaySlipDescription", "employingEntityId", "includeInPortableLongServiceLeaveReport", "portableLongServiceLeaveId", "isExemptFromFloodLevy", "isExemptFromPayrollTax", "isSeasonalWorker", "maximumQuarterlySuperContributionsBase", "superThresholdAmount", "singleTouchPayroll", "dateOfBirth", "gender", "title", "middleName", "preferredName", "previousSurname", "emailAddress", "homePhone", "mobilePhone", "workPhone", "bankAccount1_AccountName", "bankAccount1_AccountNumber", "bankAccount1_AllocatedPercentage", "bankAccount1_BSB", "bankAccount1_FixedAmount", "bankAccount2_AccountName", "bankAccount2_AccountNumber", "bankAccount2_AllocatedPercentage", "bankAccount2_BSB", "bankAccount2_FixedAmount", "bankAccount3_AccountName", "bankAccount3_AccountNumber", "bankAccount3_AllocatedPercentage", "bankAccount3_BSB", "bankAccount3_FixedAmount", "emergencyContact1_Address", "emergencyContact1_AlternateContactNumber", "emergencyContact1_ContactNumber", "emergencyContact1_Name", "emergencyContact1_Relationship", "emergencyContact2_Address", "emergencyContact2_AlternateContactNumber", "emergencyContact2_ContactNumber", "emergencyContact2_Name", "emergencyContact2_Relationship", "postalStreetAddress", "postalAddressLine2", "postalPostCode", "postalCountry", "postalState", "postalSuburb", "postalAddressIsOverseas", "residentialStreetAddress", "residentialAddressLine2", "residentialPostCode", "residentialCountry", "residentialState", "residentialSuburb", "residentialAddressIsOverseas", "taxFileNumber", "taxCategory", "taxVariation", "claimTaxFreeThreshold", "claimMedicareLevyReduction", "medicareLevyExemption", "medicareLevyReductionDependentCount", "medicareLevyReductionSpouse", "medicareLevySurchargeWithholdingTier", "seniorsTaxOffset", "otherTaxOffset", "stslDebt", "hasWithholdingVariation", "dateTaxFileDeclarationReported", "dateTaxFileDeclarationSigned", "superFund1_AllocatedPercentage", "superFund1_EmployerNominatedFund", "superFund1_FixedAmount", "superFund1_FundName", "superFund1_MemberNumber", "superFund1_ProductCode", "superFund2_AllocatedPercentage", "superFund2_EmployerNominatedFund", "superFund2_FixedAmount", "superFund2_FundName", "superFund2_MemberNumber", "superFund2_ProductCode", "superFund3_AllocatedPercentage", "superFund3_EmployerNominatedFund", "superFund3_FixedAmount", "superFund3_FundName", "superFund3_MemberNumber", "superFund3_ProductCode", "contractorABN", "employingEntityABN", "hasApprovedWorkingHolidayVisa", "workingHolidayVisaCountry", "workingHolidayVisaStartDate"];
|
|
375
|
+
/** Access tier for method-level authorization */
|
|
376
|
+
export type AccessTier = 'standard' | 'restricted';
|
|
377
|
+
/**
|
|
378
|
+
* Access tier for each data method.
|
|
379
|
+
*
|
|
380
|
+
* Standard: operational data (locations, groups, kiosks, roster shifts, report fields).
|
|
381
|
+
* Restricted: employee-level data (employees, standard hours, leave requests, employee reports).
|
|
382
|
+
* Utility methods (validate, clear, invalidate) are not included.
|
|
383
|
+
*/
|
|
384
|
+
export declare const METHOD_TIERS: Record<string, AccessTier>;
|
package/dist/types.js
CHANGED
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
// ============================================================================
|
|
8
8
|
// Field Key Constants (whitelists for pickFields)
|
|
9
9
|
// ============================================================================
|
|
10
|
+
/** Whitelisted fields for EHLeaveRequest */
|
|
11
|
+
export const LEAVE_REQUEST_FIELDS = [
|
|
12
|
+
'id', 'employeeId', 'leaveCategoryId', 'employee', 'leaveCategory',
|
|
13
|
+
'fromDate', 'toDate', 'totalHours', 'hoursApplied', 'notes', 'status',
|
|
14
|
+
];
|
|
10
15
|
/** Whitelisted fields for EHLocation */
|
|
11
16
|
export const LOCATION_FIELDS = [
|
|
12
17
|
'id', 'parentId', 'name', 'externalId', 'source',
|
|
@@ -118,3 +123,23 @@ export const AU_EMPLOYEE_FIELDS = [
|
|
|
118
123
|
...AU_EMPLOYEE_OPERATIONAL_FIELDS,
|
|
119
124
|
...AU_EMPLOYEE_PII_FIELDS,
|
|
120
125
|
];
|
|
126
|
+
/**
|
|
127
|
+
* Access tier for each data method.
|
|
128
|
+
*
|
|
129
|
+
* Standard: operational data (locations, groups, kiosks, roster shifts, report fields).
|
|
130
|
+
* Restricted: employee-level data (employees, standard hours, leave requests, employee reports).
|
|
131
|
+
* Utility methods (validate, clear, invalidate) are not included.
|
|
132
|
+
*/
|
|
133
|
+
export const METHOD_TIERS = {
|
|
134
|
+
getLocations: 'standard',
|
|
135
|
+
getEmployeeGroups: 'standard',
|
|
136
|
+
getKiosks: 'standard',
|
|
137
|
+
getKioskStaff: 'standard',
|
|
138
|
+
getRosterShifts: 'standard',
|
|
139
|
+
getReportFields: 'standard',
|
|
140
|
+
getEmployees: 'restricted',
|
|
141
|
+
getLeaveRequests: 'restricted',
|
|
142
|
+
getEmployee: 'restricted',
|
|
143
|
+
getStandardHours: 'restricted',
|
|
144
|
+
getEmployeeDetailsReport: 'restricted',
|
|
145
|
+
};
|