@markwharton/eh-payroll 3.0.1 → 3.2.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 +29 -29
- package/dist/client.d.ts +16 -16
- package/dist/client.js +25 -25
- package/dist/constants.d.ts +4 -4
- package/dist/constants.js +3 -3
- package/dist/employee-types.generated.d.ts +61 -58
- package/dist/employee-types.generated.js +0 -8
- package/dist/errors.d.ts +5 -5
- package/dist/errors.js +6 -6
- package/dist/index.d.ts +16 -9
- package/dist/index.js +17 -6
- package/dist/types.d.ts +48 -44
- package/dist/types.js +23 -23
- package/package.json +1 -1
- package/dist/cache.d.ts +0 -38
- package/dist/cache.js +0 -73
- package/dist/rate-limiter.d.ts +0 -33
- package/dist/rate-limiter.js +0 -63
package/README.md
CHANGED
|
@@ -11,9 +11,9 @@ npm install @markwharton/eh-payroll
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
import {
|
|
14
|
+
import { PayrollClient } from '@markwharton/eh-payroll';
|
|
15
15
|
|
|
16
|
-
const client = new
|
|
16
|
+
const client = new PayrollClient({
|
|
17
17
|
apiKey: 'xxx',
|
|
18
18
|
businessId: 123,
|
|
19
19
|
region: 'au', // 'au' | 'nz' | 'uk' | 'sg' | 'my' (default: 'au')
|
|
@@ -25,15 +25,15 @@ if (!validation.ok) throw new Error(validation.error);
|
|
|
25
25
|
|
|
26
26
|
// Get all employees
|
|
27
27
|
const empResult = await client.getEmployees();
|
|
28
|
-
if (empResult.ok) console.log(empResult.data); //
|
|
28
|
+
if (empResult.ok) console.log(empResult.data); // PayrollAuEmployee[]
|
|
29
29
|
|
|
30
30
|
// Get employees filtered by location
|
|
31
31
|
const filteredResult = await client.getEmployees({ locationId: 5 });
|
|
32
|
-
if (filteredResult.ok) console.log(filteredResult.data); //
|
|
32
|
+
if (filteredResult.ok) console.log(filteredResult.data); // PayrollAuEmployee[]
|
|
33
33
|
|
|
34
34
|
// Get roster shifts for a date range (auto-paginates)
|
|
35
35
|
const rosterResult = await client.getRosterShifts('2026-02-03', '2026-02-09');
|
|
36
|
-
if (rosterResult.ok) console.log(rosterResult.data); //
|
|
36
|
+
if (rosterResult.ok) console.log(rosterResult.data); // PayrollRosterShift[]
|
|
37
37
|
|
|
38
38
|
// Get roster shifts with filters
|
|
39
39
|
const pubResult = await client.getRosterShifts('2026-02-03', '2026-02-09', {
|
|
@@ -41,7 +41,7 @@ const pubResult = await client.getRosterShifts('2026-02-03', '2026-02-09', {
|
|
|
41
41
|
shiftStatus: 'Published',
|
|
42
42
|
selectAllRoles: true
|
|
43
43
|
});
|
|
44
|
-
if (pubResult.ok) console.log(pubResult.data); //
|
|
44
|
+
if (pubResult.ok) console.log(pubResult.data); // PayrollRosterShift[]
|
|
45
45
|
|
|
46
46
|
// Get leave requests for a date range (all filters server-side)
|
|
47
47
|
const leaveResult = await client.getLeaveRequests({
|
|
@@ -49,27 +49,27 @@ const leaveResult = await client.getLeaveRequests({
|
|
|
49
49
|
toDate: '2026-03-31',
|
|
50
50
|
status: 'Approved',
|
|
51
51
|
});
|
|
52
|
-
if (leaveResult.ok) console.log(leaveResult.data); //
|
|
52
|
+
if (leaveResult.ok) console.log(leaveResult.data); // PayrollLeaveRequest[]
|
|
53
53
|
|
|
54
54
|
// Get business locations
|
|
55
55
|
const locResult = await client.getLocations();
|
|
56
|
-
if (locResult.ok) console.log(locResult.data); //
|
|
56
|
+
if (locResult.ok) console.log(locResult.data); // PayrollLocation[]
|
|
57
57
|
|
|
58
58
|
// List kiosks
|
|
59
59
|
const kioskResult = await client.getKiosks();
|
|
60
|
-
if (kioskResult.ok) console.log(kioskResult.data); //
|
|
60
|
+
if (kioskResult.ok) console.log(kioskResult.data); // PayrollKiosk[]
|
|
61
61
|
|
|
62
62
|
// Get kiosk staff (time and attendance)
|
|
63
63
|
const staffResult = await client.getKioskStaff(kioskId);
|
|
64
|
-
if (staffResult.ok) console.log(staffResult.data); //
|
|
64
|
+
if (staffResult.ok) console.log(staffResult.data); // PayrollKioskEmployee[]
|
|
65
65
|
|
|
66
66
|
// Get employee groups
|
|
67
67
|
const groupResult = await client.getEmployeeGroups();
|
|
68
|
-
if (groupResult.ok) console.log(groupResult.data); //
|
|
68
|
+
if (groupResult.ok) console.log(groupResult.data); // PayrollEmployeeGroup[]
|
|
69
69
|
|
|
70
70
|
// Get standard hours for an employee (includes FTE value)
|
|
71
71
|
const hoursResult = await client.getStandardHours(employeeId);
|
|
72
|
-
if (hoursResult.ok) console.log(hoursResult.data); //
|
|
72
|
+
if (hoursResult.ok) console.log(hoursResult.data); // PayrollStandardHours
|
|
73
73
|
|
|
74
74
|
```
|
|
75
75
|
|
|
@@ -82,17 +82,17 @@ All methods return `Result<T>` — see [api-core Result Pattern](../../README.md
|
|
|
82
82
|
| Method | Parameters | Returns |
|
|
83
83
|
|--------|-----------|---------|
|
|
84
84
|
| `validateApiKey()` | — | `Result<void>` |
|
|
85
|
-
| `getEmployees(options?)` | `
|
|
86
|
-
| `getEmployee(employeeId)` | `number` | `Result<
|
|
87
|
-
| `getEmployeeImage(employeeId)` | `number` | `Result<
|
|
88
|
-
| `getStandardHours(employeeId)` | `number` | `Result<
|
|
89
|
-
| `getLocations()` | — | `Result<
|
|
90
|
-
| `getEmployeeGroups()` | — | `Result<
|
|
91
|
-
| `getRosterShifts(from, to, options?)` | `string, string,
|
|
92
|
-
| `getKiosks()` | — | `Result<
|
|
93
|
-
| `getKioskStaff(kioskId, options?)` | `number,
|
|
94
|
-
| `getLeaveRequests(options?)` | `
|
|
95
|
-
| `getEmployeeLeaveRequests(employeeId, options?)` | `number,
|
|
85
|
+
| `getEmployees(options?)` | `PayrollEmployeeOptions?` | `Result<PayrollAuEmployee[]>` |
|
|
86
|
+
| `getEmployee(employeeId)` | `number` | `Result<PayrollAuEmployee>` |
|
|
87
|
+
| `getEmployeeImage(employeeId)` | `number` | `Result<PayrollEmployeeImage>` |
|
|
88
|
+
| `getStandardHours(employeeId)` | `number` | `Result<PayrollStandardHours>` |
|
|
89
|
+
| `getLocations()` | — | `Result<PayrollLocation[]>` |
|
|
90
|
+
| `getEmployeeGroups()` | — | `Result<PayrollEmployeeGroup[]>` |
|
|
91
|
+
| `getRosterShifts(from, to, options?)` | `string, string, PayrollRosterShiftOptions?` | `Result<PayrollRosterShift[]>` |
|
|
92
|
+
| `getKiosks()` | — | `Result<PayrollKiosk[]>` |
|
|
93
|
+
| `getKioskStaff(kioskId, options?)` | `number, PayrollKioskStaffOptions?` | `Result<PayrollKioskEmployee[]>` |
|
|
94
|
+
| `getLeaveRequests(options?)` | `PayrollLeaveRequestOptions?` | `Result<PayrollLeaveRequest[]>` |
|
|
95
|
+
| `getEmployeeLeaveRequests(employeeId, options?)` | `number, PayrollEmployeeLeaveRequestOptions?` | `Result<PayrollLeaveRequest[]>` |
|
|
96
96
|
| `clearCache()` | — | `void` |
|
|
97
97
|
| `invalidateEmployeeCache()` | — | `void` |
|
|
98
98
|
| `invalidateLeaveRequestCache()` | — | `void` |
|
|
@@ -106,13 +106,13 @@ Returns leave requests with all filters applied server-side. The business-level
|
|
|
106
106
|
|
|
107
107
|
**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.
|
|
108
108
|
|
|
109
|
-
**`
|
|
109
|
+
**`PayrollLeaveRequestOptions`:**
|
|
110
110
|
|
|
111
111
|
| Option | Type | Description |
|
|
112
112
|
|--------|------|-------------|
|
|
113
113
|
| `fromDate` | `string` | Start date filter (YYYY-MM-DD) |
|
|
114
114
|
| `toDate` | `string` | End date filter (YYYY-MM-DD) |
|
|
115
|
-
| `status` | `
|
|
115
|
+
| `status` | `PayrollLeaveRequestStatus` | `'Approved'`, `'Pending'`, `'Rejected'`, or `'Cancelled'` |
|
|
116
116
|
| `employeeId` | `number` | Filter by employee ID |
|
|
117
117
|
| `leaveCategoryId` | `number` | Filter by leave category ID |
|
|
118
118
|
| `locationId` | `number` | Filter by location ID |
|
|
@@ -123,11 +123,11 @@ Returns leave requests with all filters applied server-side. The business-level
|
|
|
123
123
|
|
|
124
124
|
Returns leave requests for a specific employee using the per-employee endpoint with OData pagination.
|
|
125
125
|
|
|
126
|
-
**`
|
|
126
|
+
**`PayrollEmployeeLeaveRequestOptions`:**
|
|
127
127
|
|
|
128
128
|
| Option | Type | Description |
|
|
129
129
|
|--------|------|-------------|
|
|
130
|
-
| `status` | `
|
|
130
|
+
| `status` | `PayrollLeaveRequestStatus` | `'Approved'`, `'Pending'`, `'Rejected'`, or `'Cancelled'` |
|
|
131
131
|
| `fromDate` | `string` | Start date filter (ISO 8601) |
|
|
132
132
|
| `toDate` | `string` | End date filter (ISO 8601) |
|
|
133
133
|
|
|
@@ -142,7 +142,7 @@ The [KeyPay Swagger spec](https://api.keypay.com.au/swagger-au.json) uses incons
|
|
|
142
142
|
## Configuration
|
|
143
143
|
|
|
144
144
|
```typescript
|
|
145
|
-
const client = new
|
|
145
|
+
const client = new PayrollClient({
|
|
146
146
|
apiKey: 'your-api-key', // Required: used as Basic Auth username
|
|
147
147
|
businessId: 12345, // Required: business ID
|
|
148
148
|
region: 'au', // Optional: au, nz, uk, sg, my (default: au)
|
|
@@ -159,7 +159,7 @@ const client = new EHClient({
|
|
|
159
159
|
});
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
-
`
|
|
162
|
+
`PayrollConfig` extends `ClientConfig` from api-core, which provides the `baseUrl`, `onRequest`, `retry`, and `cacheInstance` fields. `apiKey`, `businessId`, `region`, `cache`, and `rateLimitPerSecond` are payroll-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.
|
|
163
163
|
|
|
164
164
|
### Cache TTLs
|
|
165
165
|
|
package/dist/client.d.ts
CHANGED
|
@@ -6,15 +6,15 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @see https://api.keypay.com.au/
|
|
8
8
|
*/
|
|
9
|
-
import type {
|
|
10
|
-
import type {
|
|
9
|
+
import type { PayrollConfig, PayrollLeaveRequest, PayrollLeaveRequestOptions, PayrollEmployeeLeaveRequestOptions, PayrollEmployeeOptions, PayrollStandardHours, PayrollLocation, PayrollEmployeeGroup, PayrollRosterShift, PayrollRosterShiftOptions, PayrollKiosk, PayrollKioskEmployee, PayrollKioskStaffOptions, PayrollEmployeeImage } from './types.js';
|
|
10
|
+
import type { PayrollEmployee } from './employee-types.generated.js';
|
|
11
11
|
import type { Result } from '@markwharton/api-core';
|
|
12
12
|
/**
|
|
13
13
|
* Employment Hero Payroll API Client
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
16
|
* ```typescript
|
|
17
|
-
* const client = new
|
|
17
|
+
* const client = new PayrollClient({ apiKey: 'xxx', businessId: 123 });
|
|
18
18
|
*
|
|
19
19
|
* // Validate credentials
|
|
20
20
|
* await client.validateApiKey();
|
|
@@ -23,7 +23,7 @@ import type { Result } from '@markwharton/api-core';
|
|
|
23
23
|
* const { data: employees } = await client.getEmployees();
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
-
export declare class
|
|
26
|
+
export declare class PayrollClient {
|
|
27
27
|
private readonly apiKey;
|
|
28
28
|
private readonly businessId;
|
|
29
29
|
private readonly baseUrl;
|
|
@@ -33,7 +33,7 @@ export declare class EHClient {
|
|
|
33
33
|
private readonly retryConfig?;
|
|
34
34
|
private readonly rateLimiter?;
|
|
35
35
|
private readonly persistRestricted;
|
|
36
|
-
constructor(config:
|
|
36
|
+
constructor(config: PayrollConfig);
|
|
37
37
|
/** Cache options for restricted-tier methods: skip persistent stores when persistRestricted is false. */
|
|
38
38
|
private get restrictedPersistOpt();
|
|
39
39
|
/** Route through cache if enabled, skipping failed Results. */
|
|
@@ -101,22 +101,22 @@ export declare class EHClient {
|
|
|
101
101
|
*
|
|
102
102
|
* @see https://api.keypay.com.au/australia/reference/leave-requests/au-business-hours-leave-request--list-leave-requests.html
|
|
103
103
|
*/
|
|
104
|
-
getLeaveRequests(options?:
|
|
104
|
+
getLeaveRequests(options?: PayrollLeaveRequestOptions): Promise<Result<PayrollLeaveRequest[]>>;
|
|
105
105
|
/**
|
|
106
106
|
* Get leave requests for a specific employee
|
|
107
107
|
*
|
|
108
108
|
* Uses the per-employee endpoint with OData pagination.
|
|
109
109
|
* Optional filters for status and date range.
|
|
110
110
|
*/
|
|
111
|
-
getEmployeeLeaveRequests(employeeId: number, options?:
|
|
111
|
+
getEmployeeLeaveRequests(employeeId: number, options?: PayrollEmployeeLeaveRequestOptions): Promise<Result<PayrollLeaveRequest[]>>;
|
|
112
112
|
/**
|
|
113
113
|
* Get all employees
|
|
114
114
|
*/
|
|
115
|
-
getEmployees(options?:
|
|
115
|
+
getEmployees(options?: PayrollEmployeeOptions): Promise<Result<PayrollEmployee[]>>;
|
|
116
116
|
/**
|
|
117
117
|
* Get a single employee by ID
|
|
118
118
|
*/
|
|
119
|
-
getEmployee(employeeId: number): Promise<Result<
|
|
119
|
+
getEmployee(employeeId: number): Promise<Result<PayrollEmployee>>;
|
|
120
120
|
/**
|
|
121
121
|
* Get employee profile image
|
|
122
122
|
*
|
|
@@ -124,19 +124,19 @@ export declare class EHClient {
|
|
|
124
124
|
*
|
|
125
125
|
* @see https://api.keypay.com.au/australia/reference/employee/au-employee--get-employee-profile-image.html
|
|
126
126
|
*/
|
|
127
|
-
getEmployeeImage(employeeId: number): Promise<Result<
|
|
127
|
+
getEmployeeImage(employeeId: number): Promise<Result<PayrollEmployeeImage>>;
|
|
128
128
|
/**
|
|
129
129
|
* Get standard hours for an employee (includes FTE value)
|
|
130
130
|
*/
|
|
131
|
-
getStandardHours(employeeId: number): Promise<Result<
|
|
131
|
+
getStandardHours(employeeId: number): Promise<Result<PayrollStandardHours>>;
|
|
132
132
|
/**
|
|
133
133
|
* Get all business locations
|
|
134
134
|
*/
|
|
135
|
-
getLocations(): Promise<Result<
|
|
135
|
+
getLocations(): Promise<Result<PayrollLocation[]>>;
|
|
136
136
|
/**
|
|
137
137
|
* Get all employee groups
|
|
138
138
|
*/
|
|
139
|
-
getEmployeeGroups(): Promise<Result<
|
|
139
|
+
getEmployeeGroups(): Promise<Result<PayrollEmployeeGroup[]>>;
|
|
140
140
|
/**
|
|
141
141
|
* Get roster shifts for a date range
|
|
142
142
|
*
|
|
@@ -144,16 +144,16 @@ export declare class EHClient {
|
|
|
144
144
|
* @param toDate - End date (YYYY-MM-DD)
|
|
145
145
|
* @param options - Optional filters
|
|
146
146
|
*/
|
|
147
|
-
getRosterShifts(fromDate: string, toDate: string, options?:
|
|
147
|
+
getRosterShifts(fromDate: string, toDate: string, options?: PayrollRosterShiftOptions): Promise<Result<PayrollRosterShift[]>>;
|
|
148
148
|
/**
|
|
149
149
|
* Get all kiosks for the business
|
|
150
150
|
*/
|
|
151
|
-
getKiosks(): Promise<Result<
|
|
151
|
+
getKiosks(): Promise<Result<PayrollKiosk[]>>;
|
|
152
152
|
/**
|
|
153
153
|
* Get kiosk staff for time and attendance
|
|
154
154
|
*
|
|
155
155
|
* @param kioskId - Kiosk identifier
|
|
156
156
|
* @param options - Optional query parameters
|
|
157
157
|
*/
|
|
158
|
-
getKioskStaff(kioskId: number, options?:
|
|
158
|
+
getKioskStaff(kioskId: number, options?: PayrollKioskStaffOptions): Promise<Result<PayrollKioskEmployee[]>>;
|
|
159
159
|
}
|
package/dist/client.js
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { ENTITIES } from './types.js';
|
|
10
10
|
import { buildBasicAuthHeader } from './utils.js';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { parsePayrollErrorResponse } from './errors.js';
|
|
12
|
+
import { PAYROLL_API_BASE, PAYROLL_REGION_URLS } from './constants.js';
|
|
13
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;
|
|
@@ -21,7 +21,7 @@ const DEFAULT_PAGE_SIZE = 100;
|
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
23
|
* ```typescript
|
|
24
|
-
* const client = new
|
|
24
|
+
* const client = new PayrollClient({ apiKey: 'xxx', businessId: 123 });
|
|
25
25
|
*
|
|
26
26
|
* // Validate credentials
|
|
27
27
|
* await client.validateApiKey();
|
|
@@ -30,11 +30,11 @@ const DEFAULT_PAGE_SIZE = 100;
|
|
|
30
30
|
* const { data: employees } = await client.getEmployees();
|
|
31
31
|
* ```
|
|
32
32
|
*/
|
|
33
|
-
export class
|
|
33
|
+
export class PayrollClient {
|
|
34
34
|
constructor(config) {
|
|
35
35
|
this.apiKey = config.apiKey;
|
|
36
36
|
this.businessId = config.businessId;
|
|
37
|
-
this.baseUrl = config.baseUrl ?? (config.region ?
|
|
37
|
+
this.baseUrl = config.baseUrl ?? (config.region ? PAYROLL_REGION_URLS[config.region] : PAYROLL_API_BASE);
|
|
38
38
|
this.onRequest = config.onRequest;
|
|
39
39
|
// Initialize cache if configured
|
|
40
40
|
this.cache = resolveClientCache(config);
|
|
@@ -150,7 +150,7 @@ export class EHClient {
|
|
|
150
150
|
* Fetch a URL and parse the response, with standardized error handling.
|
|
151
151
|
*/
|
|
152
152
|
fetchAndParse(url, parse, fetchOptions) {
|
|
153
|
-
return fetchAndParseResponse(() => this.fetch(url, fetchOptions), parse,
|
|
153
|
+
return fetchAndParseResponse(() => this.fetch(url, fetchOptions), parse, parsePayrollErrorResponse);
|
|
154
154
|
}
|
|
155
155
|
/**
|
|
156
156
|
* Fetch all pages of a paginated endpoint.
|
|
@@ -172,7 +172,7 @@ export class EHClient {
|
|
|
172
172
|
const response = await this.fetch(url);
|
|
173
173
|
if (!response.ok) {
|
|
174
174
|
const errorText = await response.text();
|
|
175
|
-
const { message } =
|
|
175
|
+
const { message } = parsePayrollErrorResponse(errorText, response.status);
|
|
176
176
|
return err(message, response.status);
|
|
177
177
|
}
|
|
178
178
|
const page = (await response.json())
|
|
@@ -258,10 +258,10 @@ export class EHClient {
|
|
|
258
258
|
params.set('GroupBy', options.groupBy);
|
|
259
259
|
if (options?.restrictOverlappingLeave)
|
|
260
260
|
params.set('RestrictOverlappingLeave', 'true');
|
|
261
|
-
const url = this.businessUrl(ENTITIES.
|
|
261
|
+
const url = this.businessUrl(ENTITIES.PayrollLeaveRequest.path, params);
|
|
262
262
|
return this.fetchAndParse(url, async (r) => {
|
|
263
263
|
return (await r.json())
|
|
264
|
-
.map(item => pickFields(item, ENTITIES.
|
|
264
|
+
.map(item => pickFields(item, ENTITIES.PayrollLeaveRequest.fields));
|
|
265
265
|
});
|
|
266
266
|
}, this.restrictedPersistOpt);
|
|
267
267
|
}
|
|
@@ -280,7 +280,7 @@ export class EHClient {
|
|
|
280
280
|
if (options?.toDate)
|
|
281
281
|
parts.push(`to:${options.toDate}`);
|
|
282
282
|
const cacheKey = parts.join(':');
|
|
283
|
-
const entityPath = ENTITIES.
|
|
283
|
+
const entityPath = ENTITIES.PayrollEmployeeLeaveRequest.path.replace('{employeeId}', String(employeeId));
|
|
284
284
|
return this.cached(cacheKey, this.cacheTtl.leaveRequestsTtl, () => {
|
|
285
285
|
const params = new URLSearchParams();
|
|
286
286
|
params.set('$top', String(DEFAULT_PAGE_SIZE));
|
|
@@ -296,7 +296,7 @@ export class EHClient {
|
|
|
296
296
|
return this.fetchPaginated((skip) => {
|
|
297
297
|
params.set('$skip', String(skip));
|
|
298
298
|
return this.businessUrl(entityPath, params);
|
|
299
|
-
}, ENTITIES.
|
|
299
|
+
}, ENTITIES.PayrollEmployeeLeaveRequest.fields);
|
|
300
300
|
}, this.restrictedPersistOpt);
|
|
301
301
|
}
|
|
302
302
|
// ============================================================================
|
|
@@ -321,8 +321,8 @@ export class EHClient {
|
|
|
321
321
|
params.set('$top', String(DEFAULT_PAGE_SIZE));
|
|
322
322
|
return this.fetchPaginated((skip) => {
|
|
323
323
|
params.set('$skip', String(skip));
|
|
324
|
-
return this.businessUrl(ENTITIES.
|
|
325
|
-
}, ENTITIES.
|
|
324
|
+
return this.businessUrl(ENTITIES.PayrollEmployee.path, params);
|
|
325
|
+
}, ENTITIES.PayrollEmployee.fields);
|
|
326
326
|
}, this.restrictedPersistOpt);
|
|
327
327
|
}
|
|
328
328
|
/**
|
|
@@ -330,9 +330,9 @@ export class EHClient {
|
|
|
330
330
|
*/
|
|
331
331
|
async getEmployee(employeeId) {
|
|
332
332
|
return this.cached(`employee:${employeeId}`, this.cacheTtl.employeesTtl, async () => {
|
|
333
|
-
const url = this.businessUrl(`${ENTITIES.
|
|
333
|
+
const url = this.businessUrl(`${ENTITIES.PayrollEmployee.path}/${employeeId}`);
|
|
334
334
|
return this.fetchAndParse(url, async (r) => {
|
|
335
|
-
return pickFields(await r.json(), ENTITIES.
|
|
335
|
+
return pickFields(await r.json(), ENTITIES.PayrollEmployee.fields);
|
|
336
336
|
});
|
|
337
337
|
}, this.restrictedPersistOpt);
|
|
338
338
|
}
|
|
@@ -375,8 +375,8 @@ export class EHClient {
|
|
|
375
375
|
const params = new URLSearchParams({ '$top': String(DEFAULT_PAGE_SIZE) });
|
|
376
376
|
return this.fetchPaginated((skip) => {
|
|
377
377
|
params.set('$skip', String(skip));
|
|
378
|
-
return this.businessUrl(ENTITIES.
|
|
379
|
-
}, ENTITIES.
|
|
378
|
+
return this.businessUrl(ENTITIES.PayrollLocation.path, params);
|
|
379
|
+
}, ENTITIES.PayrollLocation.fields);
|
|
380
380
|
});
|
|
381
381
|
}
|
|
382
382
|
// ============================================================================
|
|
@@ -390,8 +390,8 @@ export class EHClient {
|
|
|
390
390
|
const params = new URLSearchParams({ '$top': String(DEFAULT_PAGE_SIZE) });
|
|
391
391
|
return this.fetchPaginated((skip) => {
|
|
392
392
|
params.set('$skip', String(skip));
|
|
393
|
-
return this.businessUrl(ENTITIES.
|
|
394
|
-
}, ENTITIES.
|
|
393
|
+
return this.businessUrl(ENTITIES.PayrollEmployeeGroup.path, params);
|
|
394
|
+
}, ENTITIES.PayrollEmployeeGroup.fields);
|
|
395
395
|
});
|
|
396
396
|
}
|
|
397
397
|
// ============================================================================
|
|
@@ -473,8 +473,8 @@ export class EHClient {
|
|
|
473
473
|
params.set('IncludeWarnings', 'true');
|
|
474
474
|
return this.fetchPaginated((skip) => {
|
|
475
475
|
params.set('CurrentPage', String(skip / DEFAULT_PAGE_SIZE + 1));
|
|
476
|
-
return this.businessUrl(ENTITIES.
|
|
477
|
-
}, ENTITIES.
|
|
476
|
+
return this.businessUrl(ENTITIES.PayrollRosterShift.path, params);
|
|
477
|
+
}, ENTITIES.PayrollRosterShift.fields);
|
|
478
478
|
});
|
|
479
479
|
}
|
|
480
480
|
// ============================================================================
|
|
@@ -488,8 +488,8 @@ export class EHClient {
|
|
|
488
488
|
const params = new URLSearchParams({ '$top': String(DEFAULT_PAGE_SIZE) });
|
|
489
489
|
return this.fetchPaginated((skip) => {
|
|
490
490
|
params.set('$skip', String(skip));
|
|
491
|
-
return this.businessUrl(ENTITIES.
|
|
492
|
-
}, ENTITIES.
|
|
491
|
+
return this.businessUrl(ENTITIES.PayrollKiosk.path, params);
|
|
492
|
+
}, ENTITIES.PayrollKiosk.fields);
|
|
493
493
|
});
|
|
494
494
|
}
|
|
495
495
|
/**
|
|
@@ -507,10 +507,10 @@ export class EHClient {
|
|
|
507
507
|
if (options?.restrictCurrentShiftsToCurrentKioskLocation) {
|
|
508
508
|
params.set('restrictCurrentShiftsToCurrentKioskLocation', 'true');
|
|
509
509
|
}
|
|
510
|
-
const url = this.businessUrl(ENTITIES.
|
|
510
|
+
const url = this.businessUrl(ENTITIES.PayrollKioskEmployee.path.replace('{kioskId}', String(kioskId)), params);
|
|
511
511
|
return this.fetchAndParse(url, async (r) => {
|
|
512
512
|
return (await r.json())
|
|
513
|
-
.map(item => pickFields(item, ENTITIES.
|
|
513
|
+
.map(item => pickFields(item, ENTITIES.PayrollKioskEmployee.fields));
|
|
514
514
|
});
|
|
515
515
|
});
|
|
516
516
|
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Employment Hero Payroll Constants
|
|
3
3
|
*/
|
|
4
4
|
/** Supported API regions */
|
|
5
|
-
export type
|
|
5
|
+
export type PayrollRegion = 'au' | 'nz' | 'uk' | 'sg' | 'my';
|
|
6
6
|
/** Base URLs for each region */
|
|
7
|
-
export declare const
|
|
8
|
-
/** Default
|
|
9
|
-
export declare const
|
|
7
|
+
export declare const PAYROLL_REGION_URLS: Record<PayrollRegion, string>;
|
|
8
|
+
/** Default Payroll API base URL (AU) */
|
|
9
|
+
export declare const PAYROLL_API_BASE: string;
|
package/dist/constants.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
* Employment Hero Payroll Constants
|
|
3
3
|
*/
|
|
4
4
|
/** Base URLs for each region */
|
|
5
|
-
export const
|
|
5
|
+
export const PAYROLL_REGION_URLS = {
|
|
6
6
|
au: 'https://api.yourpayroll.com.au/api/v2',
|
|
7
7
|
nz: 'https://apinz.yourpayroll.io/api/v2',
|
|
8
8
|
uk: 'https://api.yourpayroll.co.uk/api/v2',
|
|
9
9
|
sg: 'https://apisg.yourpayroll.io/api/v2',
|
|
10
10
|
my: 'https://apimy.yourpayroll.io/api/v2',
|
|
11
11
|
};
|
|
12
|
-
/** Default
|
|
13
|
-
export const
|
|
12
|
+
/** Default Payroll API base URL (AU) */
|
|
13
|
+
export const PAYROLL_API_BASE = PAYROLL_REGION_URLS.au;
|
|
@@ -4,26 +4,48 @@
|
|
|
4
4
|
* Generated from KeyPay AU Swagger spec. DO NOT EDIT MANUALLY.
|
|
5
5
|
* Run: npx tsx scripts/generate-types.ts
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Total fields: 139
|
|
8
8
|
*/
|
|
9
|
-
|
|
10
|
-
export
|
|
9
|
+
export type PayrollCloselyHeldReporting = 'PerQuarter' | 'PerPayRun';
|
|
10
|
+
export type PayrollEmployeeStatus = 'Active' | 'Terminated' | 'Incomplete';
|
|
11
|
+
export type PayrollLeaveAccrualStartDateType = 'EmployeeStartDate' | 'SpecifiedDate' | 'CalendarYear' | 'CategorySpecificDate';
|
|
12
|
+
export type PayrollMedicareLevySurchargeWithholdingTier = 'Tier1' | 'Tier2' | 'Tier3';
|
|
13
|
+
export type PayrollSingleTouchPayrollCategory = 'CloselyHeld' | 'ForeignEmployment' | 'InboundAssignee' | 'LabourHire' | 'OtherSpecifiedPayments' | 'SalaryAndWages' | 'WorkingHolidayMaker' | 'SeasonalWorker';
|
|
14
|
+
export type PayrollTaxCategory = 'Actor_WithTaxFreeThreshold' | 'Actor_NoTaxFreeThreshold' | 'Actor_LimitedPerformancePerWeek' | 'Actor_Promotional' | 'HorticulturalistShearer_WithTaxFreeThreshold' | 'HorticulturalistShearer_ForeignResident' | 'SeniorPensioner_Single' | 'SeniorPensioner_Married' | 'SeniorPensioner_SeparatedCoupleIllness' | 'ATODefined_DeathBeneficiary' | 'ATODefined_DownwardVariation' | 'ATODefined_NonEmployee' | 'DailyCasual';
|
|
15
|
+
/** AU employee from unstructured endpoint (139 fields) */
|
|
16
|
+
export interface PayrollEmployee {
|
|
11
17
|
anniversaryDate: string | null;
|
|
18
|
+
australianResident: boolean;
|
|
19
|
+
automaticallyApplyPublicHolidayNotWorkedEarningsLines: boolean;
|
|
12
20
|
automaticallyPayEmployee: string | null;
|
|
21
|
+
awardId: number | null;
|
|
13
22
|
bankAccount1_AccountName: string | null;
|
|
14
23
|
bankAccount1_AccountNumber: string | null;
|
|
15
24
|
bankAccount1_AllocatedPercentage: number | null;
|
|
25
|
+
bankAccount1_BSB: string | null;
|
|
16
26
|
bankAccount1_FixedAmount: number | null;
|
|
17
27
|
bankAccount2_AccountName: string | null;
|
|
18
28
|
bankAccount2_AccountNumber: string | null;
|
|
19
29
|
bankAccount2_AllocatedPercentage: number | null;
|
|
30
|
+
bankAccount2_BSB: string | null;
|
|
20
31
|
bankAccount2_FixedAmount: number | null;
|
|
21
32
|
bankAccount3_AccountName: string | null;
|
|
22
33
|
bankAccount3_AccountNumber: string | null;
|
|
23
34
|
bankAccount3_AllocatedPercentage: number | null;
|
|
35
|
+
bankAccount3_BSB: string | null;
|
|
24
36
|
bankAccount3_FixedAmount: number | null;
|
|
37
|
+
businessAwardPackage: string | null;
|
|
38
|
+
claimMedicareLevyReduction: boolean;
|
|
39
|
+
claimTaxFreeThreshold: boolean;
|
|
40
|
+
closelyHeldEmployee: boolean;
|
|
41
|
+
closelyHeldReporting: PayrollCloselyHeldReporting | null;
|
|
42
|
+
contractorABN: string | null;
|
|
25
43
|
dateCreated: string | null;
|
|
26
44
|
dateOfBirth: string | null;
|
|
45
|
+
dateTaxFileDeclarationReported: string | null;
|
|
46
|
+
dateTaxFileDeclarationSigned: string | null;
|
|
47
|
+
disableAutoProgression: boolean;
|
|
48
|
+
dvlPaySlipDescription: string | null;
|
|
27
49
|
emailAddress: string | null;
|
|
28
50
|
emergencyContact1_Address: string | null;
|
|
29
51
|
emergencyContact1_AlternateContactNumber: string | null;
|
|
@@ -35,95 +57,71 @@ export interface EHEmployeeCommon {
|
|
|
35
57
|
emergencyContact2_ContactNumber: string | null;
|
|
36
58
|
emergencyContact2_Name: string | null;
|
|
37
59
|
emergencyContact2_Relationship: string | null;
|
|
60
|
+
employingEntityABN: string | null;
|
|
61
|
+
employingEntityId: string | null;
|
|
62
|
+
employmentAgreement: string | null;
|
|
63
|
+
employmentAgreementId: number | null;
|
|
64
|
+
employmentType: string | null;
|
|
38
65
|
endDate: string | null;
|
|
39
66
|
externalId: string | null;
|
|
40
67
|
firstName: string | null;
|
|
41
68
|
gender: string | null;
|
|
69
|
+
hasApprovedWorkingHolidayVisa: boolean;
|
|
70
|
+
hasWithholdingVariation: boolean;
|
|
42
71
|
homePhone: string | null;
|
|
72
|
+
hoursPerDay: number | null;
|
|
43
73
|
hoursPerWeek: number | null;
|
|
44
74
|
id: number | null;
|
|
75
|
+
includeInPortableLongServiceLeaveReport: boolean;
|
|
45
76
|
isEnabledForTimesheets: string | null;
|
|
77
|
+
isExemptFromFloodLevy: boolean;
|
|
78
|
+
isExemptFromPayrollTax: boolean;
|
|
79
|
+
isSeasonalWorker: boolean;
|
|
46
80
|
jobTitle: string | null;
|
|
47
|
-
leaveAccrualStartDateType:
|
|
81
|
+
leaveAccrualStartDateType: PayrollLeaveAccrualStartDateType | null;
|
|
48
82
|
leaveTemplate: string | null;
|
|
49
83
|
leaveYearStart: string | null;
|
|
50
84
|
locations: string | null;
|
|
85
|
+
maximumQuarterlySuperContributionsBase: number | null;
|
|
86
|
+
medicareLevyExemption: string | null;
|
|
87
|
+
medicareLevyReductionDependentCount: number | null;
|
|
88
|
+
medicareLevyReductionSpouse: boolean;
|
|
89
|
+
medicareLevySurchargeWithholdingTier: PayrollMedicareLevySurchargeWithholdingTier | null;
|
|
51
90
|
middleName: string | null;
|
|
52
91
|
mobilePhone: string | null;
|
|
92
|
+
otherTaxOffset: boolean;
|
|
53
93
|
overrideTemplateRate: string | null;
|
|
54
94
|
payConditionRuleSet: string | null;
|
|
55
95
|
payRateTemplate: string | null;
|
|
56
96
|
paySchedule: string | null;
|
|
57
97
|
paySlipNotificationType: string | null;
|
|
98
|
+
portableLongServiceLeaveId: string | null;
|
|
99
|
+
postalAddressIsOverseas: boolean;
|
|
58
100
|
postalAddressLine2: string | null;
|
|
59
101
|
postalCountry: string | null;
|
|
60
102
|
postalPostCode: string | null;
|
|
103
|
+
postalState: string | null;
|
|
61
104
|
postalStreetAddress: string | null;
|
|
105
|
+
postalSuburb: string | null;
|
|
62
106
|
preferredName: string | null;
|
|
107
|
+
previousSurname: string | null;
|
|
63
108
|
primaryLocation: string | null;
|
|
64
109
|
primaryPayCategory: string | null;
|
|
65
110
|
rate: number | null;
|
|
66
111
|
rateUnit: string | null;
|
|
67
112
|
reportingDimensionValues: string | null;
|
|
113
|
+
residentialAddressIsOverseas: boolean;
|
|
68
114
|
residentialAddressLine2: string | null;
|
|
69
115
|
residentialCountry: string | null;
|
|
70
116
|
residentialPostCode: string | null;
|
|
71
|
-
residentialStreetAddress: string | null;
|
|
72
|
-
rosteringNotificationChoices: string | null;
|
|
73
|
-
startDate: string | null;
|
|
74
|
-
status: 'Active' | 'Terminated' | 'Incomplete' | null;
|
|
75
|
-
surname: string | null;
|
|
76
|
-
tags: string | null;
|
|
77
|
-
title: string | null;
|
|
78
|
-
workPhone: string | null;
|
|
79
|
-
workTypes: string | null;
|
|
80
|
-
}
|
|
81
|
-
/** AU region employee (70 region-specific fields) */
|
|
82
|
-
export interface EHEmployee extends EHEmployeeCommon {
|
|
83
|
-
australianResident: boolean;
|
|
84
|
-
automaticallyApplyPublicHolidayNotWorkedEarningsLines: boolean;
|
|
85
|
-
awardId: number | null;
|
|
86
|
-
bankAccount1_BSB: string | null;
|
|
87
|
-
bankAccount2_BSB: string | null;
|
|
88
|
-
bankAccount3_BSB: string | null;
|
|
89
|
-
businessAwardPackage: string | null;
|
|
90
|
-
claimMedicareLevyReduction: boolean;
|
|
91
|
-
claimTaxFreeThreshold: boolean;
|
|
92
|
-
closelyHeldEmployee: boolean;
|
|
93
|
-
closelyHeldReporting: 'PerQuarter' | 'PerPayRun' | null;
|
|
94
|
-
contractorABN: string | null;
|
|
95
|
-
dateTaxFileDeclarationReported: string | null;
|
|
96
|
-
dateTaxFileDeclarationSigned: string | null;
|
|
97
|
-
disableAutoProgression: boolean;
|
|
98
|
-
dvlPaySlipDescription: string | null;
|
|
99
|
-
employingEntityABN: string | null;
|
|
100
|
-
employingEntityId: string | null;
|
|
101
|
-
employmentAgreement: string | null;
|
|
102
|
-
employmentAgreementId: number | null;
|
|
103
|
-
employmentType: string | null;
|
|
104
|
-
hasApprovedWorkingHolidayVisa: boolean;
|
|
105
|
-
hasWithholdingVariation: boolean;
|
|
106
|
-
hoursPerDay: number | null;
|
|
107
|
-
includeInPortableLongServiceLeaveReport: boolean;
|
|
108
|
-
isExemptFromFloodLevy: boolean;
|
|
109
|
-
isExemptFromPayrollTax: boolean;
|
|
110
|
-
isSeasonalWorker: boolean;
|
|
111
|
-
maximumQuarterlySuperContributionsBase: number | null;
|
|
112
|
-
medicareLevyExemption: string | null;
|
|
113
|
-
medicareLevyReductionDependentCount: number | null;
|
|
114
|
-
medicareLevyReductionSpouse: boolean;
|
|
115
|
-
medicareLevySurchargeWithholdingTier: 'Tier1' | 'Tier2' | 'Tier3' | null;
|
|
116
|
-
otherTaxOffset: boolean;
|
|
117
|
-
portableLongServiceLeaveId: string | null;
|
|
118
|
-
postalAddressIsOverseas: boolean;
|
|
119
|
-
postalState: string | null;
|
|
120
|
-
postalSuburb: string | null;
|
|
121
|
-
previousSurname: string | null;
|
|
122
|
-
residentialAddressIsOverseas: boolean;
|
|
123
117
|
residentialState: string | null;
|
|
118
|
+
residentialStreetAddress: string | null;
|
|
124
119
|
residentialSuburb: string | null;
|
|
120
|
+
rosteringNotificationChoices: string | null;
|
|
125
121
|
seniorsTaxOffset: boolean;
|
|
126
|
-
singleTouchPayroll:
|
|
122
|
+
singleTouchPayroll: PayrollSingleTouchPayrollCategory | null;
|
|
123
|
+
startDate: string | null;
|
|
124
|
+
status: PayrollEmployeeStatus | null;
|
|
127
125
|
stslDebt: boolean;
|
|
128
126
|
superFund1_AllocatedPercentage: number | null;
|
|
129
127
|
superFund1_EmployerNominatedFund: boolean;
|
|
@@ -144,10 +142,15 @@ export interface EHEmployee extends EHEmployeeCommon {
|
|
|
144
142
|
superFund3_MemberNumber: string | null;
|
|
145
143
|
superFund3_ProductCode: string | null;
|
|
146
144
|
superThresholdAmount: number | null;
|
|
147
|
-
|
|
145
|
+
surname: string | null;
|
|
146
|
+
tags: string | null;
|
|
147
|
+
taxCategory: PayrollTaxCategory | null;
|
|
148
148
|
taxFileNumber: string | null;
|
|
149
149
|
taxVariation: number | null;
|
|
150
150
|
terminationReason: string | null;
|
|
151
|
+
title: string | null;
|
|
151
152
|
workingHolidayVisaCountry: string | null;
|
|
152
153
|
workingHolidayVisaStartDate: string | null;
|
|
154
|
+
workPhone: string | null;
|
|
155
|
+
workTypes: string | null;
|
|
153
156
|
}
|