@markwharton/eh-payroll 2.3.0 → 2.5.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
@@ -71,15 +71,6 @@ if (groupResult.ok) console.log(groupResult.data); // EHEmployeeGroup[]
71
71
  const hoursResult = await client.getStandardHours(employeeId);
72
72
  if (hoursResult.ok) console.log(hoursResult.data); // EHStandardHours
73
73
 
74
- // Discover available report columns
75
- const fieldsResult = await client.getReportFields();
76
- if (fieldsResult.ok) console.log(fieldsResult.data); // EHReportField[]
77
-
78
- // Run Employee Details Report with selected columns
79
- const reportResult = await client.getEmployeeDetailsReport({
80
- selectedColumns: ['FirstName', 'Surname', 'ExternalId']
81
- });
82
- if (reportResult.ok) console.log(reportResult.data); // Record<string, unknown>[]
83
74
  ```
84
75
 
85
76
  ## Result Pattern
@@ -117,13 +108,15 @@ const employees = result.data;
117
108
  | `getRosterShifts(from, to, options?)` | `string, string, EHRosterShiftOptions?` | `Result<EHRosterShift[]>` |
118
109
  | `getKiosks()` | — | `Result<EHKiosk[]>` |
119
110
  | `getKioskStaff(kioskId, options?)` | `number, EHKioskStaffOptions?` | `Result<EHKioskEmployee[]>` |
120
- | `getReportFields()` | — | `Result<EHReportField[]>` |
121
111
  | `getLeaveRequests(options?)` | `EHLeaveRequestOptions?` | `Result<EHLeaveRequest[]>` |
122
- | `getEmployeeDetailsReport(options?)` | `EHEmployeeDetailsReportOptions?` | `Result<Record<string, unknown>[]>` |
123
112
 
124
113
  ### `getLeaveRequests()`
125
114
 
126
- Returns leave requests with all filters applied server-side. Unlike paginated endpoints, this returns a flat array.
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.
118
+
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.
127
120
 
128
121
  **`EHLeaveRequestOptions`:**
129
122
 
@@ -136,10 +129,6 @@ Returns leave requests with all filters applied server-side. Unlike paginated en
136
129
  | `leaveCategoryId` | `number` | Filter by leave category ID |
137
130
  | `locationId` | `number` | Filter by location ID |
138
131
 
139
- ### `getEmployeeDetailsReport()`
140
-
141
- 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).
142
-
143
132
  ### `getRosterShifts()`
144
133
 
145
134
  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.
@@ -168,7 +157,7 @@ const client = new EHClient({
168
157
  });
169
158
  ```
170
159
 
171
- `EHConfig` extends `ClientConfig` from api-core, which provides the `baseUrl`, `onRequest`, `retry`, and `cacheInstance` fields. `apiKey`, `businessId`, `region`, `cache`, and `rateLimitPerSecond` are EH-specific. Pass `cacheInstance` to use a custom cache backend (e.g., `LayeredCache` with persistent stores); otherwise `cache: {}` creates an in-memory `TTLCache`. PII data (`includePii: true`) automatically skips persistent stores.
160
+ `EHConfig` extends `ClientConfig` from api-core, which provides the `baseUrl`, `onRequest`, `retry`, and `cacheInstance` fields. `apiKey`, `businessId`, `region`, `cache`, and `rateLimitPerSecond` are EH-specific. Pass `cacheInstance` to use a custom cache backend (e.g., `LayeredCache` with persistent stores); otherwise `cache: {}` creates an in-memory `TTLCache`. Set `persistRestricted: false` to keep restricted-tier data in memory only.
172
161
 
173
162
  ### Cache TTLs
174
163
 
@@ -182,10 +171,8 @@ const client = new EHClient({
182
171
  | Leave requests | 2 min |
183
172
  | Kiosks | 5 min |
184
173
  | Kiosk staff | 1 min |
185
- | Report fields | 10 min |
186
- | Employee details report | 2 min |
187
174
 
188
- 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).
175
+ 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, restricted data handling, request coalescing).
189
176
 
190
177
  ### Rate Limiting
191
178
 
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, EHSingleEmployeeOptions, EHStandardHours, EHLocation, EHEmployeeGroup, EHRosterShift, EHRosterShiftOptions, EHKiosk, EHKioskEmployee, EHKioskStaffOptions, EHReportField, EHEmployeeDetailsReportOptions } from './types.js';
9
+ import type { EHConfig, EHLeaveRequest, EHLeaveRequestOptions, 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
  /**
@@ -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
@@ -90,7 +93,7 @@ export declare class EHClient {
90
93
  /**
91
94
  * Get a single employee by ID
92
95
  */
93
- getEmployee(employeeId: number, options?: EHSingleEmployeeOptions): Promise<Result<EHAuEmployee>>;
96
+ getEmployee(employeeId: number): Promise<Result<EHAuEmployee>>;
94
97
  /**
95
98
  * Get standard hours for an employee (includes FTE value)
96
99
  */
@@ -122,18 +125,4 @@ export declare class EHClient {
122
125
  * @param options - Optional query parameters
123
126
  */
124
127
  getKioskStaff(kioskId: number, options?: EHKioskStaffOptions): Promise<Result<EHKioskEmployee[]>>;
125
- /**
126
- * Get available fields for the Employee Details Report
127
- *
128
- * Returns the list of columns that can be requested via getEmployeeDetailsReport().
129
- * Use this to discover what data is available for the business.
130
- */
131
- getReportFields(): Promise<Result<EHReportField[]>>;
132
- /**
133
- * Get Employee Details Report
134
- *
135
- * Returns all employees with the requested columns in a single API call.
136
- * The response is dynamic (JObject[]) — field keys depend on selectedColumns.
137
- */
138
- getEmployeeDetailsReport(options?: EHEmployeeDetailsReportOptions): Promise<Result<Record<string, unknown>[]>>;
139
128
  }
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, LEAVE_REQUEST_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
9
+ import { 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';
@@ -49,8 +49,6 @@ export class EHClient {
49
49
  rosterShiftsTtl: config.cache?.rosterShiftsTtl ?? 120000,
50
50
  kiosksTtl: config.cache?.kiosksTtl ?? 300000,
51
51
  kioskStaffTtl: config.cache?.kioskStaffTtl ?? 60000,
52
- reportFieldsTtl: config.cache?.reportFieldsTtl ?? 600000,
53
- employeeDetailsReportTtl: config.cache?.employeeDetailsReportTtl ?? 120000,
54
52
  };
55
53
  // Initialize retry config with defaults if provided
56
54
  this.retryConfig = resolveRetryConfig(config.retry);
@@ -59,6 +57,11 @@ export class EHClient {
59
57
  if (rateLimitPerSecond > 0) {
60
58
  this.rateLimiter = new RateLimiter(rateLimitPerSecond);
61
59
  }
60
+ this.persistRestricted = config.persistRestricted ?? true;
61
+ }
62
+ /** Cache options for restricted-tier methods: skip persistent stores when persistRestricted is false. */
63
+ get restrictedPersistOpt() {
64
+ return this.persistRestricted ? undefined : { persist: false };
62
65
  }
63
66
  /**
64
67
  * Route through cache if enabled, otherwise call factory directly.
@@ -240,7 +243,7 @@ export class EHClient {
240
243
  return (await r.json())
241
244
  .map(item => pickFields(item, LEAVE_REQUEST_FIELDS));
242
245
  });
243
- });
246
+ }, this.restrictedPersistOpt);
244
247
  }
245
248
  // ============================================================================
246
249
  // Employees
@@ -249,16 +252,12 @@ export class EHClient {
249
252
  * Get all employees (unstructured format)
250
253
  */
251
254
  async getEmployees(options) {
252
- const fields = options?.includePii ? AU_EMPLOYEE_FIELDS : AU_EMPLOYEE_OPERATIONAL_FIELDS;
253
255
  const parts = ['employees'];
254
256
  if (options?.payScheduleId != null)
255
257
  parts.push(`ps:${options.payScheduleId}`);
256
258
  if (options?.locationId != null)
257
259
  parts.push(`loc:${options.locationId}`);
258
- if (options?.includePii)
259
- parts.push('pii');
260
260
  const cacheKey = parts.join(':');
261
- const persistOpt = options?.includePii ? { persist: false } : undefined;
262
261
  return this.cached(cacheKey, this.cacheTtl.employeesTtl, () => {
263
262
  const params = new URLSearchParams();
264
263
  if (options?.payScheduleId != null)
@@ -269,22 +268,19 @@ export class EHClient {
269
268
  return this.fetchPaginated((skip) => {
270
269
  params.set('$skip', String(skip));
271
270
  return `${this.baseUrl}/business/${this.businessId}/employee/unstructured?${params}`;
272
- }, fields);
273
- }, persistOpt);
271
+ }, AU_EMPLOYEE_FIELDS);
272
+ }, this.restrictedPersistOpt);
274
273
  }
275
274
  /**
276
275
  * Get a single employee by ID
277
276
  */
278
- async getEmployee(employeeId, options) {
279
- const fields = options?.includePii ? AU_EMPLOYEE_FIELDS : AU_EMPLOYEE_OPERATIONAL_FIELDS;
280
- const cacheKey = options?.includePii ? `employee:${employeeId}:pii` : `employee:${employeeId}`;
281
- const persistOpt = options?.includePii ? { persist: false } : undefined;
282
- return this.cached(cacheKey, this.cacheTtl.employeesTtl, async () => {
277
+ async getEmployee(employeeId) {
278
+ return this.cached(`employee:${employeeId}`, this.cacheTtl.employeesTtl, async () => {
283
279
  const url = `${this.baseUrl}/business/${this.businessId}/employee/unstructured/${employeeId}`;
284
280
  return this.fetchAndParse(url, async (r) => {
285
- return pickFields(await r.json(), fields);
281
+ return pickFields(await r.json(), AU_EMPLOYEE_FIELDS);
286
282
  });
287
- }, persistOpt);
283
+ }, this.restrictedPersistOpt);
288
284
  }
289
285
  // ============================================================================
290
286
  // Standard Hours
@@ -298,7 +294,7 @@ export class EHClient {
298
294
  return this.fetchAndParse(url, async (r) => {
299
295
  return await r.json();
300
296
  }, { description: `Get standard hours for employee ${employeeId}` });
301
- });
297
+ }, this.restrictedPersistOpt);
302
298
  }
303
299
  // ============================================================================
304
300
  // Locations
@@ -450,61 +446,4 @@ export class EHClient {
450
446
  });
451
447
  });
452
448
  }
453
- // ============================================================================
454
- // Employee Details Report
455
- // ============================================================================
456
- /**
457
- * Get available fields for the Employee Details Report
458
- *
459
- * Returns the list of columns that can be requested via getEmployeeDetailsReport().
460
- * Use this to discover what data is available for the business.
461
- */
462
- async getReportFields() {
463
- return this.cached('reportfields', this.cacheTtl.reportFieldsTtl, async () => {
464
- const url = `${this.baseUrl}/business/${this.businessId}/report/employeedetails/fields`;
465
- return this.fetchAndParse(url, async (r) => {
466
- return await r.json();
467
- });
468
- });
469
- }
470
- /**
471
- * Get Employee Details Report
472
- *
473
- * Returns all employees with the requested columns in a single API call.
474
- * The response is dynamic (JObject[]) — field keys depend on selectedColumns.
475
- */
476
- async getEmployeeDetailsReport(options) {
477
- const parts = ['report:employeedetails'];
478
- if (options?.selectedColumns?.length)
479
- parts.push(`cols:${options.selectedColumns.join(',')}`);
480
- if (options?.locationId != null)
481
- parts.push(`loc:${options.locationId}`);
482
- if (options?.employingEntityId != null)
483
- parts.push(`ee:${options.employingEntityId}`);
484
- if (options?.includeActive != null)
485
- parts.push(`a:${options.includeActive}`);
486
- if (options?.includeInactive != null)
487
- parts.push(`i:${options.includeInactive}`);
488
- const cacheKey = parts.join(':');
489
- return this.cached(cacheKey, this.cacheTtl.employeeDetailsReportTtl, async () => {
490
- const params = new URLSearchParams();
491
- if (options?.selectedColumns) {
492
- for (const col of options.selectedColumns) {
493
- params.append('selectedColumns', col);
494
- }
495
- }
496
- if (options?.locationId != null)
497
- params.set('locationId', String(options.locationId));
498
- if (options?.employingEntityId != null)
499
- params.set('employingEntityId', String(options.employingEntityId));
500
- if (options?.includeActive != null)
501
- params.set('includeActive', String(options.includeActive));
502
- if (options?.includeInactive != null)
503
- params.set('includeInactive', String(options.includeInactive));
504
- const url = this.businessUrl('report/employeedetails', params);
505
- return this.fetchAndParse(url, async (r) => {
506
- return await r.json();
507
- });
508
- });
509
- }
510
449
  }
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, 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';
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';
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, LEAVE_REQUEST_FIELDS, LOCATION_FIELDS, EMPLOYEE_GROUP_FIELDS, ROSTER_SHIFT_FIELDS, KIOSK_FIELDS, KIOSK_EMPLOYEE_FIELDS, } from './types.js';
25
+ export { 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
@@ -29,10 +29,6 @@ export interface EHCacheConfig {
29
29
  kiosksTtl?: number;
30
30
  /** TTL for kiosk staff (default: 60000 = 1 min) */
31
31
  kioskStaffTtl?: number;
32
- /** TTL for report fields (default: 600000 = 10 min) */
33
- reportFieldsTtl?: number;
34
- /** TTL for employee details report (default: 120000 = 2 min) */
35
- employeeDetailsReportTtl?: number;
36
32
  }
37
33
  /** @deprecated Use `RetryConfig` from `@markwharton/api-core` directly. */
38
34
  export type EHRetryConfig = RetryConfig;
@@ -50,6 +46,8 @@ export interface EHConfig extends ClientConfig {
50
46
  cache?: EHCacheConfig;
51
47
  /** Max requests per second (default: 5 per API spec). Set 0 to disable. */
52
48
  rateLimitPerSecond?: number;
49
+ /** Whether to persist restricted-tier data in persistent cache stores (default: true). Set false to keep restricted data in memory only. */
50
+ persistRestricted?: boolean;
53
51
  }
54
52
  /**
55
53
  * Employee from unstructured endpoint
@@ -235,15 +233,6 @@ export interface EHEmployeeOptions {
235
233
  payScheduleId?: number;
236
234
  /** Filter by location ID */
237
235
  locationId?: number;
238
- /** Include PII fields (default: false — operational fields only) */
239
- includePii?: boolean;
240
- }
241
- /**
242
- * Options for getEmployee (single)
243
- */
244
- export interface EHSingleEmployeeOptions {
245
- /** Include PII fields (default: false — operational fields only) */
246
- includePii?: boolean;
247
236
  }
248
237
  /**
249
238
  * Options for getRosterShifts
@@ -320,32 +309,6 @@ export interface EHKioskStaffOptions {
320
309
  /** Restrict current shifts to current kiosk location (default: false) */
321
310
  restrictCurrentShiftsToCurrentKioskLocation?: boolean;
322
311
  }
323
- /**
324
- * Available field for the Employee Details Report
325
- *
326
- * From GET /business/{id}/report/employeedetails/fields
327
- */
328
- export interface EHReportField {
329
- /** Field identifier (used in selectedColumns) */
330
- value: string;
331
- /** Human-readable field name */
332
- displayText: string;
333
- }
334
- /**
335
- * Options for getEmployeeDetailsReport
336
- */
337
- export interface EHEmployeeDetailsReportOptions {
338
- /** Column names to include in the report */
339
- selectedColumns?: string[];
340
- /** Filter by location ID */
341
- locationId?: number;
342
- /** Filter by employing entity ID */
343
- employingEntityId?: number;
344
- /** Include active employees (default: true) */
345
- includeActive?: boolean;
346
- /** Include inactive employees (default: false) */
347
- includeInactive?: boolean;
348
- }
349
312
  /** Whitelisted fields for EHLeaveRequest */
350
313
  export declare const LEAVE_REQUEST_FIELDS: readonly ["id", "employeeId", "leaveCategoryId", "employee", "leaveCategory", "fromDate", "toDate", "totalHours", "hoursApplied", "notes", "status"];
351
314
  /** Whitelisted fields for EHLocation */
@@ -358,15 +321,15 @@ export declare const KIOSK_EMPLOYEE_FIELDS: readonly ["employeeId", "firstName",
358
321
  export declare const EMPLOYEE_GROUP_FIELDS: readonly ["id", "name"];
359
322
  /** Whitelisted fields for EHRosterShift */
360
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"];
326
+ /** Access tier for method-level authorization */
327
+ export type AccessTier = 'standard' | 'restricted';
361
328
  /**
362
- * Operational fields for EHAuEmployee (52 fields)
363
- * Identity, employment structure, pay config, scheduling, leave, AU compliance.
364
- */
365
- export declare const AU_EMPLOYEE_OPERATIONAL_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"];
366
- /**
367
- * PII fields for EHAuEmployee (87 fields)
368
- * Personal data, contact info, bank accounts, addresses, tax, super, emergency contacts.
329
+ * Access tier for each data method.
330
+ *
331
+ * Standard: operational data (locations, groups, kiosks, roster shifts).
332
+ * Restricted: employee-level data (employees, standard hours, leave requests).
333
+ * Utility methods (validate, clear, invalidate) are not included.
369
334
  */
370
- 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"];
371
- /** All whitelisted fields for EHAuEmployee (operational + PII) */
372
- 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"];
335
+ export declare const METHOD_TIERS: Record<string, AccessTier>;
package/dist/types.js CHANGED
@@ -41,11 +41,8 @@ export const ROSTER_SHIFT_FIELDS = [
41
41
  'workTypeId', 'workTypeName', 'startTime', 'endTime',
42
42
  'notes', 'published', 'accepted',
43
43
  ];
44
- /**
45
- * Operational fields for EHAuEmployee (52 fields)
46
- * Identity, employment structure, pay config, scheduling, leave, AU compliance.
47
- */
48
- export const AU_EMPLOYEE_OPERATIONAL_FIELDS = [
44
+ /** Whitelisted fields for EHAuEmployee (139 fields) */
45
+ export const AU_EMPLOYEE_FIELDS = [
49
46
  // Identity
50
47
  'id', 'externalId', 'firstName', 'surname', 'status',
51
48
  // Dates
@@ -71,12 +68,6 @@ export const AU_EMPLOYEE_OPERATIONAL_FIELDS = [
71
68
  'isExemptFromFloodLevy', 'isExemptFromPayrollTax', 'isSeasonalWorker',
72
69
  'maximumQuarterlySuperContributionsBase', 'superThresholdAmount',
73
70
  'singleTouchPayroll',
74
- ];
75
- /**
76
- * PII fields for EHAuEmployee (87 fields)
77
- * Personal data, contact info, bank accounts, addresses, tax, super, emergency contacts.
78
- */
79
- export const AU_EMPLOYEE_PII_FIELDS = [
80
71
  // Personal
81
72
  'dateOfBirth', 'gender', 'title', 'middleName', 'preferredName', 'previousSurname',
82
73
  // Contact
@@ -118,8 +109,21 @@ export const AU_EMPLOYEE_PII_FIELDS = [
118
109
  // Visa
119
110
  'hasApprovedWorkingHolidayVisa', 'workingHolidayVisaCountry', 'workingHolidayVisaStartDate',
120
111
  ];
121
- /** All whitelisted fields for EHAuEmployee (operational + PII) */
122
- export const AU_EMPLOYEE_FIELDS = [
123
- ...AU_EMPLOYEE_OPERATIONAL_FIELDS,
124
- ...AU_EMPLOYEE_PII_FIELDS,
125
- ];
112
+ /**
113
+ * Access tier for each data method.
114
+ *
115
+ * Standard: operational data (locations, groups, kiosks, roster shifts).
116
+ * Restricted: employee-level data (employees, standard hours, leave requests).
117
+ * Utility methods (validate, clear, invalidate) are not included.
118
+ */
119
+ export const METHOD_TIERS = {
120
+ getLocations: 'standard',
121
+ getEmployeeGroups: 'standard',
122
+ getKiosks: 'standard',
123
+ getKioskStaff: 'standard',
124
+ getRosterShifts: 'standard',
125
+ getEmployees: 'restricted',
126
+ getLeaveRequests: 'restricted',
127
+ getEmployee: 'restricted',
128
+ getStandardHours: 'restricted',
129
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markwharton/eh-payroll",
3
- "version": "2.3.0",
3
+ "version": "2.5.0",
4
4
  "description": "Employment Hero Payroll API client",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",