@markwharton/eh-payroll 2.5.0 → 2.6.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 CHANGED
@@ -75,25 +75,7 @@ if (hoursResult.ok) console.log(hoursResult.data); // EHStandardHours
75
75
 
76
76
  ## Result Pattern
77
77
 
78
- All methods return `Result<T>` objects rather than throwing exceptions. Always check `ok` before accessing `data`:
79
-
80
- ```typescript
81
- interface Result<T> {
82
- ok: boolean;
83
- data?: T; // present when ok is true
84
- error?: string; // present when ok is false
85
- status?: number; // HTTP status code on error
86
- }
87
- ```
88
-
89
- ```typescript
90
- const result = await client.getEmployees();
91
- if (!result.ok) {
92
- console.error(result.error, result.status);
93
- return;
94
- }
95
- const employees = result.data;
96
- ```
78
+ All methods return `Result<T>` see [api-core Result Pattern](../../README.md#result-pattern). Always check `ok` before accessing `data`.
97
79
 
98
80
  ## API Reference
99
81
 
@@ -109,14 +91,19 @@ const employees = result.data;
109
91
  | `getKiosks()` | — | `Result<EHKiosk[]>` |
110
92
  | `getKioskStaff(kioskId, options?)` | `number, EHKioskStaffOptions?` | `Result<EHKioskEmployee[]>` |
111
93
  | `getLeaveRequests(options?)` | `EHLeaveRequestOptions?` | `Result<EHLeaveRequest[]>` |
94
+ | `getEmployeeLeaveRequests(employeeId, options?)` | `number, EHEmployeeLeaveRequestOptions?` | `Result<EHLeaveRequest[]>` |
95
+ | `clearCache()` | — | `void` |
96
+ | `invalidateEmployeeCache()` | — | `void` |
97
+ | `invalidateLeaveRequestCache()` | — | `void` |
98
+ | `invalidateRosterShiftCache()` | — | `void` |
99
+ | `invalidateLocationCache()` | — | `void` |
100
+ | `invalidateKioskCache()` | — | `void` |
112
101
 
113
102
  ### `getLeaveRequests()`
114
103
 
115
- 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.
116
-
117
- **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.
104
+ Returns leave requests with all filters applied server-side. The business-level endpoint returns a flat array — no pagination.
118
105
 
119
- > **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.
106
+ **Leave requests are time-series data** unlike employees and locations which remain relatively stable, leave requests grow continuously. Always use `fromDate`/`toDate` filters to bound the result set.
120
107
 
121
108
  **`EHLeaveRequestOptions`:**
122
109
 
@@ -129,6 +116,18 @@ Returns leave requests with all filters applied server-side. The business-level
129
116
  | `leaveCategoryId` | `number` | Filter by leave category ID |
130
117
  | `locationId` | `number` | Filter by location ID |
131
118
 
119
+ ### `getEmployeeLeaveRequests()`
120
+
121
+ Returns leave requests for a specific employee using the per-employee endpoint with OData pagination.
122
+
123
+ **`EHEmployeeLeaveRequestOptions`:**
124
+
125
+ | Option | Type | Description |
126
+ |--------|------|-------------|
127
+ | `status` | `EHLeaveRequestStatus` | `'Approved'`, `'Pending'`, `'Rejected'`, or `'Cancelled'` |
128
+ | `fromDate` | `string` | Start date filter (ISO 8601) |
129
+ | `toDate` | `string` | End date filter (ISO 8601) |
130
+
132
131
  ### `getRosterShifts()`
133
132
 
134
133
  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.
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, EHLeaveRequest, EHLeaveRequestOptions, EHEmployeeOptions, EHStandardHours, EHLocation, EHEmployeeGroup, EHRosterShift, EHRosterShiftOptions, EHKiosk, EHKioskEmployee, EHKioskStaffOptions } from './types.js';
9
+ import type { EHConfig, EHLeaveRequest, EHLeaveRequestOptions, EHEmployeeLeaveRequestOptions, EHEmployeeOptions, EHStandardHours, EHLocation, EHEmployeeGroup, EHRosterShift, EHRosterShiftOptions, EHKiosk, EHKioskEmployee, EHKioskStaffOptions } from './types.js';
10
10
  import type { EHAuEmployee } from './employee-types.generated.js';
11
11
  import type { Result } from '@markwharton/api-core';
12
12
  /**
@@ -36,16 +36,32 @@ export declare class EHClient {
36
36
  constructor(config: EHConfig);
37
37
  /** Cache options for restricted-tier methods: skip persistent stores when persistRestricted is false. */
38
38
  private get restrictedPersistOpt();
39
- /**
40
- * Route through cache if enabled, otherwise call factory directly.
41
- * Failed Results (ok === false) are never cached — transient errors
42
- * shouldn't persist for the full TTL.
43
- */
39
+ /** Route through cache if enabled, skipping failed Results. */
44
40
  private cached;
45
41
  /**
46
42
  * Clear all cached API responses.
47
43
  */
48
44
  clearCache(): void;
45
+ /**
46
+ * Invalidate cached employee data (employees, individual employees, standard hours).
47
+ */
48
+ invalidateEmployeeCache(): void;
49
+ /**
50
+ * Invalidate cached leave request data (business-level and per-employee).
51
+ */
52
+ invalidateLeaveRequestCache(): void;
53
+ /**
54
+ * Invalidate cached roster shift data.
55
+ */
56
+ invalidateRosterShiftCache(): void;
57
+ /**
58
+ * Invalidate cached location data.
59
+ */
60
+ invalidateLocationCache(): void;
61
+ /**
62
+ * Invalidate cached kiosk data (kiosks and kiosk staff).
63
+ */
64
+ invalidateKioskCache(): void;
49
65
  /**
50
66
  * Build a URL for a business-scoped endpoint.
51
67
  */
@@ -74,11 +90,11 @@ export declare class EHClient {
74
90
  */
75
91
  private fetchPaginated;
76
92
  /**
77
- * Validate the API key by calling GET /user
93
+ * Validate the API key
78
94
  */
79
95
  validateApiKey(): Promise<Result<void>>;
80
96
  /**
81
- * Get leave requests (server-side filtering)
97
+ * Get leave requests
82
98
  *
83
99
  * All filter options are passed as query parameters to the API.
84
100
  * The endpoint returns a flat array (not paginated).
@@ -87,7 +103,14 @@ export declare class EHClient {
87
103
  */
88
104
  getLeaveRequests(options?: EHLeaveRequestOptions): Promise<Result<EHLeaveRequest[]>>;
89
105
  /**
90
- * Get all employees (unstructured format)
106
+ * Get leave requests for a specific employee
107
+ *
108
+ * Uses the per-employee endpoint with OData pagination.
109
+ * Optional filters for status and date range.
110
+ */
111
+ getEmployeeLeaveRequests(employeeId: number, options?: EHEmployeeLeaveRequestOptions): Promise<Result<EHLeaveRequest[]>>;
112
+ /**
113
+ * Get all employees
91
114
  */
92
115
  getEmployees(options?: EHEmployeeOptions): Promise<Result<EHAuEmployee[]>>;
93
116
  /**
package/dist/client.js CHANGED
@@ -6,11 +6,11 @@
6
6
  *
7
7
  * @see https://api.keypay.com.au/
8
8
  */
9
- import { AU_EMPLOYEE_FIELDS, LEAVE_REQUEST_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
9
+ import { ENTITIES } 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';
13
- import { TTLCache, pickFields, RateLimiter, getErrorMessage, fetchWithRetry, resolveRetryConfig, ok, okVoid, err } from '@markwharton/api-core';
13
+ import { pickFields, RateLimiter, getErrorMessage, fetchWithRetry, resolveRetryConfig, ok, okVoid, err, cachedResult, fetchAndParseResponse, resolveClientCache } from '@markwharton/api-core';
14
14
  /** Default page size for paginated endpoints */
15
15
  const DEFAULT_PAGE_SIZE = 100;
16
16
  // ============================================================================
@@ -37,9 +37,7 @@ export class EHClient {
37
37
  this.baseUrl = config.baseUrl ?? (config.region ? EH_REGION_URLS[config.region] : EH_API_BASE);
38
38
  this.onRequest = config.onRequest;
39
39
  // Initialize cache if configured
40
- if (config.cache || config.cacheInstance) {
41
- this.cache = config.cacheInstance ?? new TTLCache();
42
- }
40
+ this.cache = resolveClientCache(config);
43
41
  this.cacheTtl = {
44
42
  employeesTtl: config.cache?.employeesTtl ?? 300000,
45
43
  leaveRequestsTtl: config.cache?.leaveRequestsTtl ?? 120000,
@@ -63,18 +61,9 @@ export class EHClient {
63
61
  get restrictedPersistOpt() {
64
62
  return this.persistRestricted ? undefined : { persist: false };
65
63
  }
66
- /**
67
- * Route through cache if enabled, otherwise call factory directly.
68
- * Failed Results (ok === false) are never cached — transient errors
69
- * shouldn't persist for the full TTL.
70
- */
71
- async cached(key, ttlMs, factory, options) {
72
- if (!this.cache)
73
- return factory();
74
- return this.cache.get(key, ttlMs, factory, {
75
- ...options,
76
- shouldCache: (data) => data.ok !== false,
77
- });
64
+ /** Route through cache if enabled, skipping failed Results. */
65
+ cached(key, ttlMs, factory, options) {
66
+ return cachedResult(this.cache, key, ttlMs, factory, options);
78
67
  }
79
68
  /**
80
69
  * Clear all cached API responses.
@@ -82,6 +71,40 @@ export class EHClient {
82
71
  clearCache() {
83
72
  this.cache?.clear();
84
73
  }
74
+ /**
75
+ * Invalidate cached employee data (employees, individual employees, standard hours).
76
+ */
77
+ invalidateEmployeeCache() {
78
+ this.cache?.invalidate('employees');
79
+ this.cache?.invalidate('employee:');
80
+ this.cache?.invalidate('standardhours:');
81
+ }
82
+ /**
83
+ * Invalidate cached leave request data (business-level and per-employee).
84
+ */
85
+ invalidateLeaveRequestCache() {
86
+ this.cache?.invalidate('leaverequests');
87
+ this.cache?.invalidate('employeeleaverequests:');
88
+ }
89
+ /**
90
+ * Invalidate cached roster shift data.
91
+ */
92
+ invalidateRosterShiftCache() {
93
+ this.cache?.invalidate('rostershifts:');
94
+ }
95
+ /**
96
+ * Invalidate cached location data.
97
+ */
98
+ invalidateLocationCache() {
99
+ this.cache?.invalidate('locations');
100
+ }
101
+ /**
102
+ * Invalidate cached kiosk data (kiosks and kiosk staff).
103
+ */
104
+ invalidateKioskCache() {
105
+ this.cache?.invalidate('kiosks');
106
+ this.cache?.invalidate('kiosk:');
107
+ }
85
108
  /**
86
109
  * Build a URL for a business-scoped endpoint.
87
110
  */
@@ -126,19 +149,8 @@ export class EHClient {
126
149
  /**
127
150
  * Fetch a URL and parse the response, with standardized error handling.
128
151
  */
129
- async fetchAndParse(url, parse, fetchOptions) {
130
- try {
131
- const response = await this.fetch(url, fetchOptions);
132
- if (!response.ok) {
133
- const errorText = await response.text();
134
- const { message } = parseEHPayrollErrorResponse(errorText, response.status);
135
- return err(message, response.status);
136
- }
137
- return ok(await parse(response));
138
- }
139
- catch (error) {
140
- return err(getErrorMessage(error), 0);
141
- }
152
+ fetchAndParse(url, parse, fetchOptions) {
153
+ return fetchAndParseResponse(() => this.fetch(url, fetchOptions), parse, parseEHPayrollErrorResponse);
142
154
  }
143
155
  /**
144
156
  * Fetch all pages of a paginated endpoint.
@@ -180,7 +192,7 @@ export class EHClient {
180
192
  // Validation
181
193
  // ============================================================================
182
194
  /**
183
- * Validate the API key by calling GET /user
195
+ * Validate the API key
184
196
  */
185
197
  async validateApiKey() {
186
198
  const url = `${this.baseUrl}/user`;
@@ -202,7 +214,7 @@ export class EHClient {
202
214
  // Leave Requests
203
215
  // ============================================================================
204
216
  /**
205
- * Get leave requests (server-side filtering)
217
+ * Get leave requests
206
218
  *
207
219
  * All filter options are passed as query parameters to the API.
208
220
  * The endpoint returns a flat array (not paginated).
@@ -238,18 +250,52 @@ export class EHClient {
238
250
  params.set('LeaveCategoryId', String(options.leaveCategoryId));
239
251
  if (options?.locationId != null)
240
252
  params.set('LocationId', String(options.locationId));
241
- const url = this.businessUrl('leaverequest', params);
253
+ const url = this.businessUrl(ENTITIES.EHLeaveRequest.path, params);
242
254
  return this.fetchAndParse(url, async (r) => {
243
255
  return (await r.json())
244
- .map(item => pickFields(item, LEAVE_REQUEST_FIELDS));
256
+ .map(item => pickFields(item, ENTITIES.EHLeaveRequest.fields));
245
257
  });
246
258
  }, this.restrictedPersistOpt);
247
259
  }
260
+ /**
261
+ * Get leave requests for a specific employee
262
+ *
263
+ * Uses the per-employee endpoint with OData pagination.
264
+ * Optional filters for status and date range.
265
+ */
266
+ async getEmployeeLeaveRequests(employeeId, options) {
267
+ const parts = [`employeeleaverequests:${employeeId}`];
268
+ if (options?.status)
269
+ parts.push(`s:${options.status}`);
270
+ if (options?.fromDate)
271
+ parts.push(`from:${options.fromDate}`);
272
+ if (options?.toDate)
273
+ parts.push(`to:${options.toDate}`);
274
+ const cacheKey = parts.join(':');
275
+ const entityPath = ENTITIES.EHEmployeeLeaveRequest.path.replace('{employeeId}', String(employeeId));
276
+ return this.cached(cacheKey, this.cacheTtl.leaveRequestsTtl, () => {
277
+ const params = new URLSearchParams();
278
+ params.set('$top', String(DEFAULT_PAGE_SIZE));
279
+ const filterParts = [];
280
+ if (options?.status)
281
+ filterParts.push(`Status eq '${options.status}'`);
282
+ if (options?.fromDate)
283
+ filterParts.push(`FromDate ge datetime'${options.fromDate}'`);
284
+ if (options?.toDate)
285
+ filterParts.push(`ToDate le datetime'${options.toDate}'`);
286
+ if (filterParts.length > 0)
287
+ params.set('$filter', filterParts.join(' and '));
288
+ return this.fetchPaginated((skip) => {
289
+ params.set('$skip', String(skip));
290
+ return this.businessUrl(entityPath, params);
291
+ }, ENTITIES.EHEmployeeLeaveRequest.fields);
292
+ }, this.restrictedPersistOpt);
293
+ }
248
294
  // ============================================================================
249
295
  // Employees
250
296
  // ============================================================================
251
297
  /**
252
- * Get all employees (unstructured format)
298
+ * Get all employees
253
299
  */
254
300
  async getEmployees(options) {
255
301
  const parts = ['employees'];
@@ -267,8 +313,8 @@ export class EHClient {
267
313
  params.set('$top', String(DEFAULT_PAGE_SIZE));
268
314
  return this.fetchPaginated((skip) => {
269
315
  params.set('$skip', String(skip));
270
- return `${this.baseUrl}/business/${this.businessId}/employee/unstructured?${params}`;
271
- }, AU_EMPLOYEE_FIELDS);
316
+ return this.businessUrl(ENTITIES.EHAuEmployee.path, params);
317
+ }, ENTITIES.EHAuEmployee.fields);
272
318
  }, this.restrictedPersistOpt);
273
319
  }
274
320
  /**
@@ -276,9 +322,9 @@ export class EHClient {
276
322
  */
277
323
  async getEmployee(employeeId) {
278
324
  return this.cached(`employee:${employeeId}`, this.cacheTtl.employeesTtl, async () => {
279
- const url = `${this.baseUrl}/business/${this.businessId}/employee/unstructured/${employeeId}`;
325
+ const url = this.businessUrl(`${ENTITIES.EHAuEmployee.path}/${employeeId}`);
280
326
  return this.fetchAndParse(url, async (r) => {
281
- return pickFields(await r.json(), AU_EMPLOYEE_FIELDS);
327
+ return pickFields(await r.json(), ENTITIES.EHAuEmployee.fields);
282
328
  });
283
329
  }, this.restrictedPersistOpt);
284
330
  }
@@ -307,8 +353,8 @@ export class EHClient {
307
353
  const params = new URLSearchParams({ '$top': String(DEFAULT_PAGE_SIZE) });
308
354
  return this.fetchPaginated((skip) => {
309
355
  params.set('$skip', String(skip));
310
- return `${this.baseUrl}/business/${this.businessId}/location?${params}`;
311
- }, LOCATION_FIELDS);
356
+ return this.businessUrl(ENTITIES.EHLocation.path, params);
357
+ }, ENTITIES.EHLocation.fields);
312
358
  });
313
359
  }
314
360
  // ============================================================================
@@ -322,8 +368,8 @@ export class EHClient {
322
368
  const params = new URLSearchParams({ '$top': String(DEFAULT_PAGE_SIZE) });
323
369
  return this.fetchPaginated((skip) => {
324
370
  params.set('$skip', String(skip));
325
- return `${this.baseUrl}/business/${this.businessId}/employeegroup?${params}`;
326
- }, EMPLOYEE_GROUP_FIELDS);
371
+ return this.businessUrl(ENTITIES.EHEmployeeGroup.path, params);
372
+ }, ENTITIES.EHEmployeeGroup.fields);
327
373
  });
328
374
  }
329
375
  // ============================================================================
@@ -405,8 +451,8 @@ export class EHClient {
405
451
  params.set('IncludeWarnings', 'true');
406
452
  return this.fetchPaginated((skip) => {
407
453
  params.set('CurrentPage', String(skip / DEFAULT_PAGE_SIZE + 1));
408
- return `${this.baseUrl}/business/${this.businessId}/rostershift?${params}`;
409
- }, ROSTER_SHIFT_FIELDS);
454
+ return this.businessUrl(ENTITIES.EHRosterShift.path, params);
455
+ }, ENTITIES.EHRosterShift.fields);
410
456
  });
411
457
  }
412
458
  // ============================================================================
@@ -420,8 +466,8 @@ export class EHClient {
420
466
  const params = new URLSearchParams({ '$top': String(DEFAULT_PAGE_SIZE) });
421
467
  return this.fetchPaginated((skip) => {
422
468
  params.set('$skip', String(skip));
423
- return `${this.baseUrl}/business/${this.businessId}/kiosk?${params}`;
424
- }, KIOSK_FIELDS);
469
+ return this.businessUrl(ENTITIES.EHKiosk.path, params);
470
+ }, ENTITIES.EHKiosk.fields);
425
471
  });
426
472
  }
427
473
  /**
@@ -439,10 +485,10 @@ export class EHClient {
439
485
  if (options?.restrictCurrentShiftsToCurrentKioskLocation) {
440
486
  params.set('restrictCurrentShiftsToCurrentKioskLocation', 'true');
441
487
  }
442
- const url = this.businessUrl(`kiosk/${kioskId}/staff`, params);
488
+ const url = this.businessUrl(ENTITIES.EHKioskEmployee.path.replace('{kioskId}', String(kioskId)), params);
443
489
  return this.fetchAndParse(url, async (r) => {
444
490
  return (await r.json())
445
- .map(item => pickFields(item, KIOSK_EMPLOYEE_FIELDS));
491
+ .map(item => pickFields(item, ENTITIES.EHKioskEmployee.fields));
446
492
  });
447
493
  });
448
494
  }
package/dist/index.d.ts CHANGED
@@ -20,8 +20,8 @@
20
20
  * ```
21
21
  */
22
22
  export { EHClient } from './client.js';
23
- export type { EHConfig, EHCacheConfig, EHRetryConfig, EHLeaveRequest, EHLeaveRequestOptions, EHLeaveRequestStatus, EHEmployee, EHEmployeeOptions, EHStandardHours, EHLocation, EHEmployeeGroup, EHRosterShift, EHRosterShiftOptions, EHAttendanceStatus, EHKiosk, EHKioskEmployee, EHKioskStaffOptions, } from './types.js';
24
- export { AU_EMPLOYEE_FIELDS, LEAVE_REQUEST_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, EHEmployeeLeaveRequestOptions, EHLeaveRequestStatus, EHEmployee, EHEmployeeOptions, EHStandardHours, EHLocation, EHEmployeeGroup, EHRosterShift, EHRosterShiftOptions, EHAttendanceStatus, EHKiosk, EHKioskEmployee, EHKioskStaffOptions, } from './types.js';
24
+ export { AU_EMPLOYEE_FIELDS, LEAVE_REQUEST_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, ENTITIES, } from './types.js';
25
25
  export type { AccessTier } from './types.js';
26
26
  export { METHOD_TIERS } from './types.js';
27
27
  export type { EHAuEmployee } from './employee-types.generated.js';
package/dist/index.js CHANGED
@@ -21,8 +21,8 @@
21
21
  */
22
22
  // Main client
23
23
  export { EHClient } from './client.js';
24
- // Field key constants (whitelists for pickFields)
25
- export { AU_EMPLOYEE_FIELDS, LEAVE_REQUEST_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
24
+ // Field definitions (for pickFields)
25
+ export { AU_EMPLOYEE_FIELDS, LEAVE_REQUEST_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, ENTITIES, } from './types.js';
26
26
  export { METHOD_TIERS } from './types.js';
27
27
  // Utilities
28
28
  export { buildBasicAuthHeader } from './utils.js';
package/dist/types.d.ts CHANGED
@@ -178,7 +178,7 @@ export interface EHKioskEmployee {
178
178
  * Leave request from the Payroll API
179
179
  *
180
180
  * From GET /business/{id}/leaverequest
181
- * Field whitelist from Swagger HourLeaveRequestResponseModel.
181
+ * Fields from Swagger HourLeaveRequestResponseModel.
182
182
  */
183
183
  export interface EHLeaveRequest {
184
184
  /** Leave request ID */
@@ -225,6 +225,19 @@ export interface EHLeaveRequestOptions {
225
225
  /** Filter by location ID (→ API LocationId) */
226
226
  locationId?: number;
227
227
  }
228
+ /**
229
+ * Options for getEmployeeLeaveRequests
230
+ *
231
+ * Filters are passed as OData $filter to the per-employee endpoint.
232
+ */
233
+ export interface EHEmployeeLeaveRequestOptions {
234
+ /** Filter by status */
235
+ status?: EHLeaveRequestStatus;
236
+ /** Filter by start date (ISO 8601 date-time) */
237
+ fromDate?: string;
238
+ /** Filter by end date (ISO 8601 date-time) */
239
+ toDate?: string;
240
+ }
228
241
  /**
229
242
  * Options for getEmployees
230
243
  */
@@ -309,20 +322,231 @@ export interface EHKioskStaffOptions {
309
322
  /** Restrict current shifts to current kiosk location (default: false) */
310
323
  restrictCurrentShiftsToCurrentKioskLocation?: boolean;
311
324
  }
312
- /** Whitelisted fields for EHLeaveRequest */
313
- export declare const LEAVE_REQUEST_FIELDS: readonly ["id", "employeeId", "leaveCategoryId", "employee", "leaveCategory", "fromDate", "toDate", "totalHours", "hoursApplied", "notes", "status"];
314
- /** Whitelisted fields for EHLocation */
315
- export declare const LOCATION_FIELDS: readonly ["id", "parentId", "name", "externalId", "source", "fullyQualifiedName", "isGlobal", "state", "country"];
316
- /** Whitelisted fields for EHKiosk */
317
- export declare const KIOSK_FIELDS: readonly ["id", "externalId", "name", "locationId", "timeZone", "ianaTimeZone", "allowHigherClassificationSelection", "isLocationRequired", "isWorkTypeRequired", "restrictLocationsForEmployees", "allowEmployeeShiftSelection", "clockOnWindowMinutes", "clockOffWindowMinutes", "isPhotoRequired", "canAddEmployees", "paidBreaksEnabled"];
318
- /** Whitelisted fields for EHKioskEmployee */
319
- export declare const KIOSK_EMPLOYEE_FIELDS: readonly ["employeeId", "firstName", "surname", "name", "status", "clockOnTimeUtc", "breakStartTimeUtc", "currentShiftId", "employeeStartDate", "employeeGroupIds", "longShift", "recordedTimeUtc"];
320
- /** Whitelisted fields for EHEmployeeGroup */
321
- export declare const EMPLOYEE_GROUP_FIELDS: readonly ["id", "name"];
322
- /** Whitelisted fields for EHRosterShift */
323
- export declare const ROSTER_SHIFT_FIELDS: readonly ["id", "employeeId", "employeeName", "locationId", "locationName", "workTypeId", "workTypeName", "startTime", "endTime", "notes", "published", "accepted"];
324
- /** Whitelisted fields for EHAuEmployee (139 fields) */
325
- 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"];
325
+ /** Fields for EHLeaveRequest — set false to exclude from API responses */
326
+ export declare const LEAVE_REQUEST_FIELDS: {
327
+ readonly id: true;
328
+ readonly employeeId: true;
329
+ readonly leaveCategoryId: true;
330
+ readonly employee: true;
331
+ readonly leaveCategory: true;
332
+ readonly fromDate: true;
333
+ readonly toDate: true;
334
+ readonly totalHours: true;
335
+ readonly hoursApplied: true;
336
+ readonly notes: true;
337
+ readonly status: true;
338
+ };
339
+ /** Fields for EHLocation — set false to exclude from API responses */
340
+ export declare const LOCATION_FIELDS: {
341
+ readonly id: true;
342
+ readonly parentId: true;
343
+ readonly name: true;
344
+ readonly externalId: true;
345
+ readonly source: true;
346
+ readonly fullyQualifiedName: true;
347
+ readonly isGlobal: true;
348
+ readonly state: true;
349
+ readonly country: true;
350
+ };
351
+ /** Fields for EHKiosk — set false to exclude from API responses */
352
+ export declare const KIOSK_FIELDS: {
353
+ readonly id: true;
354
+ readonly externalId: true;
355
+ readonly name: true;
356
+ readonly locationId: true;
357
+ readonly timeZone: true;
358
+ readonly ianaTimeZone: true;
359
+ readonly allowHigherClassificationSelection: true;
360
+ readonly isLocationRequired: true;
361
+ readonly isWorkTypeRequired: true;
362
+ readonly restrictLocationsForEmployees: true;
363
+ readonly allowEmployeeShiftSelection: true;
364
+ readonly clockOnWindowMinutes: true;
365
+ readonly clockOffWindowMinutes: true;
366
+ readonly isPhotoRequired: true;
367
+ readonly canAddEmployees: true;
368
+ readonly paidBreaksEnabled: true;
369
+ };
370
+ /** Fields for EHKioskEmployee — set false to exclude from API responses */
371
+ export declare const KIOSK_EMPLOYEE_FIELDS: {
372
+ readonly employeeId: true;
373
+ readonly firstName: true;
374
+ readonly surname: true;
375
+ readonly name: true;
376
+ readonly status: true;
377
+ readonly clockOnTimeUtc: true;
378
+ readonly breakStartTimeUtc: true;
379
+ readonly currentShiftId: true;
380
+ readonly employeeStartDate: true;
381
+ readonly employeeGroupIds: true;
382
+ readonly longShift: true;
383
+ readonly recordedTimeUtc: true;
384
+ };
385
+ /** Fields for EHEmployeeGroup — set false to exclude from API responses */
386
+ export declare const EMPLOYEE_GROUP_FIELDS: {
387
+ readonly id: true;
388
+ readonly name: true;
389
+ };
390
+ /** Fields for EHRosterShift — set false to exclude from API responses */
391
+ export declare const ROSTER_SHIFT_FIELDS: {
392
+ readonly id: true;
393
+ readonly employeeId: true;
394
+ readonly employeeName: true;
395
+ readonly locationId: true;
396
+ readonly locationName: true;
397
+ readonly workTypeId: true;
398
+ readonly workTypeName: true;
399
+ readonly startTime: true;
400
+ readonly endTime: true;
401
+ readonly notes: true;
402
+ readonly published: true;
403
+ readonly accepted: true;
404
+ };
405
+ /** Fields for EHAuEmployee — set false to exclude from API responses */
406
+ export declare const AU_EMPLOYEE_FIELDS: {
407
+ readonly id: true;
408
+ readonly externalId: true;
409
+ readonly firstName: true;
410
+ readonly surname: true;
411
+ readonly status: true;
412
+ readonly startDate: true;
413
+ readonly endDate: true;
414
+ readonly anniversaryDate: false;
415
+ readonly dateCreated: false;
416
+ readonly employmentType: true;
417
+ readonly jobTitle: true;
418
+ readonly employmentAgreement: false;
419
+ readonly employmentAgreementId: false;
420
+ readonly paySchedule: false;
421
+ readonly payRateTemplate: false;
422
+ readonly rate: false;
423
+ readonly rateUnit: false;
424
+ readonly hoursPerWeek: false;
425
+ readonly hoursPerDay: false;
426
+ readonly primaryPayCategory: false;
427
+ readonly payConditionRuleSet: false;
428
+ readonly overrideTemplateRate: false;
429
+ readonly automaticallyPayEmployee: false;
430
+ readonly primaryLocation: true;
431
+ readonly locations: false;
432
+ readonly tags: false;
433
+ readonly workTypes: false;
434
+ readonly reportingDimensionValues: false;
435
+ readonly leaveAccrualStartDateType: false;
436
+ readonly leaveTemplate: false;
437
+ readonly leaveYearStart: false;
438
+ readonly isEnabledForTimesheets: false;
439
+ readonly rosteringNotificationChoices: false;
440
+ readonly paySlipNotificationType: false;
441
+ readonly terminationReason: false;
442
+ readonly australianResident: false;
443
+ readonly awardId: false;
444
+ readonly businessAwardPackage: false;
445
+ readonly automaticallyApplyPublicHolidayNotWorkedEarningsLines: false;
446
+ readonly closelyHeldEmployee: false;
447
+ readonly closelyHeldReporting: false;
448
+ readonly disableAutoProgression: false;
449
+ readonly dvlPaySlipDescription: false;
450
+ readonly employingEntityId: false;
451
+ readonly includeInPortableLongServiceLeaveReport: false;
452
+ readonly portableLongServiceLeaveId: false;
453
+ readonly isExemptFromFloodLevy: false;
454
+ readonly isExemptFromPayrollTax: false;
455
+ readonly isSeasonalWorker: false;
456
+ readonly maximumQuarterlySuperContributionsBase: false;
457
+ readonly superThresholdAmount: false;
458
+ readonly singleTouchPayroll: false;
459
+ readonly dateOfBirth: false;
460
+ readonly gender: false;
461
+ readonly title: false;
462
+ readonly middleName: false;
463
+ readonly preferredName: false;
464
+ readonly previousSurname: false;
465
+ readonly emailAddress: true;
466
+ readonly homePhone: false;
467
+ readonly mobilePhone: false;
468
+ readonly workPhone: false;
469
+ readonly bankAccount1_AccountName: false;
470
+ readonly bankAccount1_AccountNumber: false;
471
+ readonly bankAccount1_AllocatedPercentage: false;
472
+ readonly bankAccount1_BSB: false;
473
+ readonly bankAccount1_FixedAmount: false;
474
+ readonly bankAccount2_AccountName: false;
475
+ readonly bankAccount2_AccountNumber: false;
476
+ readonly bankAccount2_AllocatedPercentage: false;
477
+ readonly bankAccount2_BSB: false;
478
+ readonly bankAccount2_FixedAmount: false;
479
+ readonly bankAccount3_AccountName: false;
480
+ readonly bankAccount3_AccountNumber: false;
481
+ readonly bankAccount3_AllocatedPercentage: false;
482
+ readonly bankAccount3_BSB: false;
483
+ readonly bankAccount3_FixedAmount: false;
484
+ readonly emergencyContact1_Address: false;
485
+ readonly emergencyContact1_AlternateContactNumber: false;
486
+ readonly emergencyContact1_ContactNumber: false;
487
+ readonly emergencyContact1_Name: false;
488
+ readonly emergencyContact1_Relationship: false;
489
+ readonly emergencyContact2_Address: false;
490
+ readonly emergencyContact2_AlternateContactNumber: false;
491
+ readonly emergencyContact2_ContactNumber: false;
492
+ readonly emergencyContact2_Name: false;
493
+ readonly emergencyContact2_Relationship: false;
494
+ readonly postalStreetAddress: false;
495
+ readonly postalAddressLine2: false;
496
+ readonly postalPostCode: false;
497
+ readonly postalCountry: false;
498
+ readonly postalState: false;
499
+ readonly postalSuburb: false;
500
+ readonly postalAddressIsOverseas: false;
501
+ readonly residentialStreetAddress: false;
502
+ readonly residentialAddressLine2: false;
503
+ readonly residentialPostCode: false;
504
+ readonly residentialCountry: false;
505
+ readonly residentialState: false;
506
+ readonly residentialSuburb: false;
507
+ readonly residentialAddressIsOverseas: false;
508
+ readonly taxFileNumber: false;
509
+ readonly taxCategory: false;
510
+ readonly taxVariation: false;
511
+ readonly claimTaxFreeThreshold: false;
512
+ readonly claimMedicareLevyReduction: false;
513
+ readonly medicareLevyExemption: false;
514
+ readonly medicareLevyReductionDependentCount: false;
515
+ readonly medicareLevyReductionSpouse: false;
516
+ readonly medicareLevySurchargeWithholdingTier: false;
517
+ readonly seniorsTaxOffset: false;
518
+ readonly otherTaxOffset: false;
519
+ readonly stslDebt: false;
520
+ readonly hasWithholdingVariation: false;
521
+ readonly dateTaxFileDeclarationReported: false;
522
+ readonly dateTaxFileDeclarationSigned: false;
523
+ readonly superFund1_AllocatedPercentage: false;
524
+ readonly superFund1_EmployerNominatedFund: false;
525
+ readonly superFund1_FixedAmount: false;
526
+ readonly superFund1_FundName: false;
527
+ readonly superFund1_MemberNumber: false;
528
+ readonly superFund1_ProductCode: false;
529
+ readonly superFund2_AllocatedPercentage: false;
530
+ readonly superFund2_EmployerNominatedFund: false;
531
+ readonly superFund2_FixedAmount: false;
532
+ readonly superFund2_FundName: false;
533
+ readonly superFund2_MemberNumber: false;
534
+ readonly superFund2_ProductCode: false;
535
+ readonly superFund3_AllocatedPercentage: false;
536
+ readonly superFund3_EmployerNominatedFund: false;
537
+ readonly superFund3_FixedAmount: false;
538
+ readonly superFund3_FundName: false;
539
+ readonly superFund3_MemberNumber: false;
540
+ readonly superFund3_ProductCode: false;
541
+ readonly contractorABN: false;
542
+ readonly employingEntityABN: false;
543
+ readonly hasApprovedWorkingHolidayVisa: false;
544
+ readonly workingHolidayVisaCountry: false;
545
+ readonly workingHolidayVisaStartDate: false;
546
+ };
547
+ import type { EntityDef } from '@markwharton/api-core';
548
+ /** Entity registry — maps interface names to field specs and API path segments. */
549
+ export declare const ENTITIES: Record<string, EntityDef>;
326
550
  /** Access tier for method-level authorization */
327
551
  export type AccessTier = 'standard' | 'restricted';
328
552
  /**
package/dist/types.js CHANGED
@@ -5,110 +5,121 @@
5
5
  * Based on the API reference and KeyPay .NET SDK models.
6
6
  */
7
7
  // ============================================================================
8
- // Field Key Constants (whitelists for pickFields)
8
+ // Field Definitions (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
- ];
15
- /** Whitelisted fields for EHLocation */
16
- export const LOCATION_FIELDS = [
17
- 'id', 'parentId', 'name', 'externalId', 'source',
18
- 'fullyQualifiedName', 'isGlobal', 'state', 'country',
19
- ];
20
- /** Whitelisted fields for EHKiosk */
21
- export const KIOSK_FIELDS = [
22
- 'id', 'externalId', 'name', 'locationId', 'timeZone', 'ianaTimeZone',
23
- 'allowHigherClassificationSelection', 'isLocationRequired', 'isWorkTypeRequired',
24
- 'restrictLocationsForEmployees', 'allowEmployeeShiftSelection',
25
- 'clockOnWindowMinutes', 'clockOffWindowMinutes',
26
- 'isPhotoRequired', 'canAddEmployees', 'paidBreaksEnabled',
27
- ];
28
- /** Whitelisted fields for EHKioskEmployee */
29
- export const KIOSK_EMPLOYEE_FIELDS = [
30
- 'employeeId', 'firstName', 'surname', 'name', 'status',
31
- 'clockOnTimeUtc', 'breakStartTimeUtc', 'currentShiftId',
32
- 'employeeStartDate', 'employeeGroupIds', 'longShift', 'recordedTimeUtc',
33
- ];
34
- /** Whitelisted fields for EHEmployeeGroup */
35
- export const EMPLOYEE_GROUP_FIELDS = [
36
- 'id', 'name',
37
- ];
38
- /** Whitelisted fields for EHRosterShift */
39
- export const ROSTER_SHIFT_FIELDS = [
40
- 'id', 'employeeId', 'employeeName', 'locationId', 'locationName',
41
- 'workTypeId', 'workTypeName', 'startTime', 'endTime',
42
- 'notes', 'published', 'accepted',
43
- ];
44
- /** Whitelisted fields for EHAuEmployee (139 fields) */
45
- export const AU_EMPLOYEE_FIELDS = [
10
+ /** Fields for EHLeaveRequest — set false to exclude from API responses */
11
+ export const LEAVE_REQUEST_FIELDS = {
12
+ id: true, employeeId: true, leaveCategoryId: true, employee: true, leaveCategory: true,
13
+ fromDate: true, toDate: true, totalHours: true, hoursApplied: true, notes: true, status: true,
14
+ };
15
+ /** Fields for EHLocation — set false to exclude from API responses */
16
+ export const LOCATION_FIELDS = {
17
+ id: true, parentId: true, name: true, externalId: true, source: true,
18
+ fullyQualifiedName: true, isGlobal: true, state: true, country: true,
19
+ };
20
+ /** Fields for EHKiosk — set false to exclude from API responses */
21
+ export const KIOSK_FIELDS = {
22
+ id: true, externalId: true, name: true, locationId: true, timeZone: true, ianaTimeZone: true,
23
+ allowHigherClassificationSelection: true, isLocationRequired: true, isWorkTypeRequired: true,
24
+ restrictLocationsForEmployees: true, allowEmployeeShiftSelection: true,
25
+ clockOnWindowMinutes: true, clockOffWindowMinutes: true,
26
+ isPhotoRequired: true, canAddEmployees: true, paidBreaksEnabled: true,
27
+ };
28
+ /** Fields for EHKioskEmployee — set false to exclude from API responses */
29
+ export const KIOSK_EMPLOYEE_FIELDS = {
30
+ employeeId: true, firstName: true, surname: true, name: true, status: true,
31
+ clockOnTimeUtc: true, breakStartTimeUtc: true, currentShiftId: true,
32
+ employeeStartDate: true, employeeGroupIds: true, longShift: true, recordedTimeUtc: true,
33
+ };
34
+ /** Fields for EHEmployeeGroup — set false to exclude from API responses */
35
+ export const EMPLOYEE_GROUP_FIELDS = {
36
+ id: true, name: true,
37
+ };
38
+ /** Fields for EHRosterShift — set false to exclude from API responses */
39
+ export const ROSTER_SHIFT_FIELDS = {
40
+ id: true, employeeId: true, employeeName: true, locationId: true, locationName: true,
41
+ workTypeId: true, workTypeName: true, startTime: true, endTime: true,
42
+ notes: true, published: true, accepted: true,
43
+ };
44
+ /** Fields for EHAuEmployee set false to exclude from API responses */
45
+ export const AU_EMPLOYEE_FIELDS = {
46
46
  // Identity
47
- 'id', 'externalId', 'firstName', 'surname', 'status',
47
+ id: true, externalId: true, firstName: true, surname: true, status: true,
48
48
  // Dates
49
- 'startDate', 'endDate', 'anniversaryDate', 'dateCreated',
49
+ startDate: true, endDate: true, anniversaryDate: false, dateCreated: false,
50
50
  // Employment
51
- 'employmentType', 'jobTitle', 'employmentAgreement', 'employmentAgreementId',
51
+ employmentType: true, jobTitle: true, employmentAgreement: false, employmentAgreementId: false,
52
52
  // Pay
53
- 'paySchedule', 'payRateTemplate', 'rate', 'rateUnit', 'hoursPerWeek', 'hoursPerDay',
54
- 'primaryPayCategory', 'payConditionRuleSet', 'overrideTemplateRate', 'automaticallyPayEmployee',
53
+ paySchedule: false, payRateTemplate: false, rate: false, rateUnit: false, hoursPerWeek: false, hoursPerDay: false,
54
+ primaryPayCategory: false, payConditionRuleSet: false, overrideTemplateRate: false, automaticallyPayEmployee: false,
55
55
  // Location/org
56
- 'primaryLocation', 'locations', 'tags', 'workTypes', 'reportingDimensionValues',
56
+ primaryLocation: true, locations: false, tags: false, workTypes: false, reportingDimensionValues: false,
57
57
  // Leave
58
- 'leaveAccrualStartDateType', 'leaveTemplate', 'leaveYearStart',
58
+ leaveAccrualStartDateType: false, leaveTemplate: false, leaveYearStart: false,
59
59
  // Flags
60
- 'isEnabledForTimesheets', 'rosteringNotificationChoices', 'paySlipNotificationType', 'terminationReason',
60
+ isEnabledForTimesheets: false, rosteringNotificationChoices: false, paySlipNotificationType: false, terminationReason: false,
61
61
  // AU compliance
62
- 'australianResident', 'awardId', 'businessAwardPackage',
63
- 'automaticallyApplyPublicHolidayNotWorkedEarningsLines',
64
- 'closelyHeldEmployee', 'closelyHeldReporting',
65
- 'disableAutoProgression', 'dvlPaySlipDescription',
66
- 'employingEntityId',
67
- 'includeInPortableLongServiceLeaveReport', 'portableLongServiceLeaveId',
68
- 'isExemptFromFloodLevy', 'isExemptFromPayrollTax', 'isSeasonalWorker',
69
- 'maximumQuarterlySuperContributionsBase', 'superThresholdAmount',
70
- 'singleTouchPayroll',
62
+ australianResident: false, awardId: false, businessAwardPackage: false,
63
+ automaticallyApplyPublicHolidayNotWorkedEarningsLines: false,
64
+ closelyHeldEmployee: false, closelyHeldReporting: false,
65
+ disableAutoProgression: false, dvlPaySlipDescription: false,
66
+ employingEntityId: false,
67
+ includeInPortableLongServiceLeaveReport: false, portableLongServiceLeaveId: false,
68
+ isExemptFromFloodLevy: false, isExemptFromPayrollTax: false, isSeasonalWorker: false,
69
+ maximumQuarterlySuperContributionsBase: false, superThresholdAmount: false,
70
+ singleTouchPayroll: false,
71
71
  // Personal
72
- 'dateOfBirth', 'gender', 'title', 'middleName', 'preferredName', 'previousSurname',
72
+ dateOfBirth: false, gender: false, title: false, middleName: false, preferredName: false, previousSurname: false,
73
73
  // Contact
74
- 'emailAddress', 'homePhone', 'mobilePhone', 'workPhone',
74
+ emailAddress: true, homePhone: false, mobilePhone: false, workPhone: false,
75
75
  // Bank accounts
76
- 'bankAccount1_AccountName', 'bankAccount1_AccountNumber',
77
- 'bankAccount1_AllocatedPercentage', 'bankAccount1_BSB', 'bankAccount1_FixedAmount',
78
- 'bankAccount2_AccountName', 'bankAccount2_AccountNumber',
79
- 'bankAccount2_AllocatedPercentage', 'bankAccount2_BSB', 'bankAccount2_FixedAmount',
80
- 'bankAccount3_AccountName', 'bankAccount3_AccountNumber',
81
- 'bankAccount3_AllocatedPercentage', 'bankAccount3_BSB', 'bankAccount3_FixedAmount',
76
+ bankAccount1_AccountName: false, bankAccount1_AccountNumber: false,
77
+ bankAccount1_AllocatedPercentage: false, bankAccount1_BSB: false, bankAccount1_FixedAmount: false,
78
+ bankAccount2_AccountName: false, bankAccount2_AccountNumber: false,
79
+ bankAccount2_AllocatedPercentage: false, bankAccount2_BSB: false, bankAccount2_FixedAmount: false,
80
+ bankAccount3_AccountName: false, bankAccount3_AccountNumber: false,
81
+ bankAccount3_AllocatedPercentage: false, bankAccount3_BSB: false, bankAccount3_FixedAmount: false,
82
82
  // Emergency contacts
83
- 'emergencyContact1_Address', 'emergencyContact1_AlternateContactNumber',
84
- 'emergencyContact1_ContactNumber', 'emergencyContact1_Name', 'emergencyContact1_Relationship',
85
- 'emergencyContact2_Address', 'emergencyContact2_AlternateContactNumber',
86
- 'emergencyContact2_ContactNumber', 'emergencyContact2_Name', 'emergencyContact2_Relationship',
83
+ emergencyContact1_Address: false, emergencyContact1_AlternateContactNumber: false,
84
+ emergencyContact1_ContactNumber: false, emergencyContact1_Name: false, emergencyContact1_Relationship: false,
85
+ emergencyContact2_Address: false, emergencyContact2_AlternateContactNumber: false,
86
+ emergencyContact2_ContactNumber: false, emergencyContact2_Name: false, emergencyContact2_Relationship: false,
87
87
  // Postal address
88
- 'postalStreetAddress', 'postalAddressLine2', 'postalPostCode', 'postalCountry',
89
- 'postalState', 'postalSuburb', 'postalAddressIsOverseas',
88
+ postalStreetAddress: false, postalAddressLine2: false, postalPostCode: false, postalCountry: false,
89
+ postalState: false, postalSuburb: false, postalAddressIsOverseas: false,
90
90
  // Residential address
91
- 'residentialStreetAddress', 'residentialAddressLine2', 'residentialPostCode', 'residentialCountry',
92
- 'residentialState', 'residentialSuburb', 'residentialAddressIsOverseas',
91
+ residentialStreetAddress: false, residentialAddressLine2: false, residentialPostCode: false, residentialCountry: false,
92
+ residentialState: false, residentialSuburb: false, residentialAddressIsOverseas: false,
93
93
  // Tax
94
- 'taxFileNumber', 'taxCategory', 'taxVariation',
95
- 'claimTaxFreeThreshold', 'claimMedicareLevyReduction',
96
- 'medicareLevyExemption', 'medicareLevyReductionDependentCount',
97
- 'medicareLevyReductionSpouse', 'medicareLevySurchargeWithholdingTier',
98
- 'seniorsTaxOffset', 'otherTaxOffset', 'stslDebt',
99
- 'hasWithholdingVariation', 'dateTaxFileDeclarationReported', 'dateTaxFileDeclarationSigned',
94
+ taxFileNumber: false, taxCategory: false, taxVariation: false,
95
+ claimTaxFreeThreshold: false, claimMedicareLevyReduction: false,
96
+ medicareLevyExemption: false, medicareLevyReductionDependentCount: false,
97
+ medicareLevyReductionSpouse: false, medicareLevySurchargeWithholdingTier: false,
98
+ seniorsTaxOffset: false, otherTaxOffset: false, stslDebt: false,
99
+ hasWithholdingVariation: false, dateTaxFileDeclarationReported: false, dateTaxFileDeclarationSigned: false,
100
100
  // Super funds
101
- 'superFund1_AllocatedPercentage', 'superFund1_EmployerNominatedFund',
102
- 'superFund1_FixedAmount', 'superFund1_FundName', 'superFund1_MemberNumber', 'superFund1_ProductCode',
103
- 'superFund2_AllocatedPercentage', 'superFund2_EmployerNominatedFund',
104
- 'superFund2_FixedAmount', 'superFund2_FundName', 'superFund2_MemberNumber', 'superFund2_ProductCode',
105
- 'superFund3_AllocatedPercentage', 'superFund3_EmployerNominatedFund',
106
- 'superFund3_FixedAmount', 'superFund3_FundName', 'superFund3_MemberNumber', 'superFund3_ProductCode',
101
+ superFund1_AllocatedPercentage: false, superFund1_EmployerNominatedFund: false,
102
+ superFund1_FixedAmount: false, superFund1_FundName: false, superFund1_MemberNumber: false, superFund1_ProductCode: false,
103
+ superFund2_AllocatedPercentage: false, superFund2_EmployerNominatedFund: false,
104
+ superFund2_FixedAmount: false, superFund2_FundName: false, superFund2_MemberNumber: false, superFund2_ProductCode: false,
105
+ superFund3_AllocatedPercentage: false, superFund3_EmployerNominatedFund: false,
106
+ superFund3_FixedAmount: false, superFund3_FundName: false, superFund3_MemberNumber: false, superFund3_ProductCode: false,
107
107
  // ABNs
108
- 'contractorABN', 'employingEntityABN',
108
+ contractorABN: false, employingEntityABN: false,
109
109
  // Visa
110
- 'hasApprovedWorkingHolidayVisa', 'workingHolidayVisaCountry', 'workingHolidayVisaStartDate',
111
- ];
110
+ hasApprovedWorkingHolidayVisa: false, workingHolidayVisaCountry: false, workingHolidayVisaStartDate: false,
111
+ };
112
+ /** Entity registry — maps interface names to field specs and API path segments. */
113
+ export const ENTITIES = {
114
+ EHAuEmployee: { fields: AU_EMPLOYEE_FIELDS, path: 'employee/unstructured', apiRef: 'employee/au-employee--get-employees' },
115
+ EHLeaveRequest: { fields: LEAVE_REQUEST_FIELDS, path: 'leaverequest', apiRef: 'leaverequests/au-leave-request--get-leave-requests' },
116
+ EHEmployeeLeaveRequest: { fields: LEAVE_REQUEST_FIELDS, path: 'employee/{employeeId}/leaverequest', apiRef: 'leaverequests/au-leave-request--get-leave-requests-for-employee' },
117
+ EHLocation: { fields: LOCATION_FIELDS, path: 'location', apiRef: 'location/location--get-locations' },
118
+ EHRosterShift: { fields: ROSTER_SHIFT_FIELDS, path: 'rostershift', apiRef: 'rostershift/roster-shift--get-roster-shifts' },
119
+ EHKiosk: { fields: KIOSK_FIELDS, path: 'kiosk', apiRef: 'kiosk/kiosk--list-kiosks' },
120
+ EHKioskEmployee: { fields: KIOSK_EMPLOYEE_FIELDS, path: 'kiosk/{kioskId}/staff', apiRef: 'kiosk/kiosk--get-kiosk-staff' },
121
+ EHEmployeeGroup: { fields: EMPLOYEE_GROUP_FIELDS, path: 'employeegroup', apiRef: 'employeegroups/employee-group--get-employee-groups' },
122
+ };
112
123
  /**
113
124
  * Access tier for each data method.
114
125
  *
@@ -124,6 +135,7 @@ export const METHOD_TIERS = {
124
135
  getRosterShifts: 'standard',
125
136
  getEmployees: 'restricted',
126
137
  getLeaveRequests: 'restricted',
138
+ getEmployeeLeaveRequests: 'restricted',
127
139
  getEmployee: 'restricted',
128
140
  getStandardHours: 'restricted',
129
141
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markwharton/eh-payroll",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "description": "Employment Hero Payroll API client",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -16,7 +16,7 @@
16
16
  "clean": "rm -rf dist"
17
17
  },
18
18
  "dependencies": {
19
- "@markwharton/api-core": "^1.3.0"
19
+ "@markwharton/api-core": "^1.5.0"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/node": "^20.10.0",