@classytic/payroll 2.0.0 → 2.3.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.
Potentially problematic release.
This version of @classytic/payroll might be problematic. Click here for more details.
- package/README.md +2599 -253
- package/dist/calculators/index.d.ts +433 -0
- package/dist/calculators/index.js +283 -0
- package/dist/calculators/index.js.map +1 -0
- package/dist/core/index.d.ts +85 -251
- package/dist/core/index.js +286 -91
- package/dist/core/index.js.map +1 -1
- package/dist/employee-identity-DXhgOgXE.d.ts +473 -0
- package/dist/employee.factory-BlZqhiCk.d.ts +189 -0
- package/dist/idempotency-Cw2CWicb.d.ts +52 -0
- package/dist/index.d.ts +618 -683
- package/dist/index.js +8336 -3580
- package/dist/index.js.map +1 -1
- package/dist/jurisdiction/index.d.ts +660 -0
- package/dist/jurisdiction/index.js +533 -0
- package/dist/jurisdiction/index.js.map +1 -0
- package/dist/payroll.d.ts +261 -65
- package/dist/payroll.js +4164 -1075
- package/dist/payroll.js.map +1 -1
- package/dist/schemas/index.d.ts +1176 -783
- package/dist/schemas/index.js +368 -28
- package/dist/schemas/index.js.map +1 -1
- package/dist/services/index.d.ts +582 -3
- package/dist/services/index.js +572 -96
- package/dist/services/index.js.map +1 -1
- package/dist/shift-compliance/index.d.ts +1171 -0
- package/dist/shift-compliance/index.js +1479 -0
- package/dist/shift-compliance/index.js.map +1 -0
- package/dist/types-BN3K_Uhr.d.ts +1842 -0
- package/dist/utils/index.d.ts +22 -2
- package/dist/utils/index.js +470 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +24 -6
- package/dist/index-CTjHlCzz.d.ts +0 -721
- package/dist/plugin-D9mOr3_d.d.ts +0 -333
- package/dist/types-BSYyX2KJ.d.ts +0 -671
|
@@ -0,0 +1,1842 @@
|
|
|
1
|
+
import { Document, Types, ClientSession, Model } from 'mongoose';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @classytic/payroll - Event System
|
|
5
|
+
*
|
|
6
|
+
* Type-safe event emitter for payroll lifecycle events
|
|
7
|
+
* Enables loose coupling and extensibility
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface EmployeeHiredEventPayload {
|
|
11
|
+
employee: {
|
|
12
|
+
id: ObjectId;
|
|
13
|
+
employeeId: string;
|
|
14
|
+
position: string;
|
|
15
|
+
department?: string;
|
|
16
|
+
};
|
|
17
|
+
organizationId: ObjectId;
|
|
18
|
+
context?: OperationContext;
|
|
19
|
+
}
|
|
20
|
+
interface EmployeeTerminatedEventPayload {
|
|
21
|
+
employee: {
|
|
22
|
+
id: ObjectId;
|
|
23
|
+
employeeId: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
};
|
|
26
|
+
terminationDate: Date;
|
|
27
|
+
reason?: string;
|
|
28
|
+
organizationId: ObjectId;
|
|
29
|
+
context?: OperationContext;
|
|
30
|
+
}
|
|
31
|
+
interface EmployeeRehiredEventPayload {
|
|
32
|
+
employee: {
|
|
33
|
+
id: ObjectId;
|
|
34
|
+
employeeId: string;
|
|
35
|
+
position: string;
|
|
36
|
+
};
|
|
37
|
+
previousTerminationDate?: Date;
|
|
38
|
+
organizationId: ObjectId;
|
|
39
|
+
context?: OperationContext;
|
|
40
|
+
}
|
|
41
|
+
interface SalaryUpdatedEventPayload {
|
|
42
|
+
employee: {
|
|
43
|
+
id: ObjectId;
|
|
44
|
+
employeeId: string;
|
|
45
|
+
};
|
|
46
|
+
previousSalary: number;
|
|
47
|
+
newSalary: number;
|
|
48
|
+
effectiveFrom: Date;
|
|
49
|
+
organizationId: ObjectId;
|
|
50
|
+
context?: OperationContext;
|
|
51
|
+
}
|
|
52
|
+
interface SalaryProcessedEventPayload {
|
|
53
|
+
employee: {
|
|
54
|
+
id: ObjectId;
|
|
55
|
+
employeeId: string;
|
|
56
|
+
name?: string;
|
|
57
|
+
};
|
|
58
|
+
payroll: {
|
|
59
|
+
id: ObjectId;
|
|
60
|
+
period: {
|
|
61
|
+
month: number;
|
|
62
|
+
year: number;
|
|
63
|
+
};
|
|
64
|
+
grossAmount: number;
|
|
65
|
+
netAmount: number;
|
|
66
|
+
};
|
|
67
|
+
transactionId: ObjectId;
|
|
68
|
+
organizationId: ObjectId;
|
|
69
|
+
context?: OperationContext;
|
|
70
|
+
}
|
|
71
|
+
interface SalaryFailedEventPayload {
|
|
72
|
+
employee: {
|
|
73
|
+
id: ObjectId;
|
|
74
|
+
employeeId: string;
|
|
75
|
+
};
|
|
76
|
+
period: {
|
|
77
|
+
month: number;
|
|
78
|
+
year: number;
|
|
79
|
+
};
|
|
80
|
+
error: string;
|
|
81
|
+
organizationId: ObjectId;
|
|
82
|
+
context?: OperationContext;
|
|
83
|
+
}
|
|
84
|
+
interface PayrollCompletedEventPayload {
|
|
85
|
+
organizationId: ObjectId;
|
|
86
|
+
period: {
|
|
87
|
+
month: number;
|
|
88
|
+
year: number;
|
|
89
|
+
};
|
|
90
|
+
summary: {
|
|
91
|
+
total: number;
|
|
92
|
+
successful: number;
|
|
93
|
+
failed: number;
|
|
94
|
+
totalAmount: number;
|
|
95
|
+
};
|
|
96
|
+
context?: OperationContext;
|
|
97
|
+
}
|
|
98
|
+
interface PayrollExportedEventPayload {
|
|
99
|
+
organizationId: ObjectId;
|
|
100
|
+
dateRange: {
|
|
101
|
+
start: Date;
|
|
102
|
+
end: Date;
|
|
103
|
+
};
|
|
104
|
+
recordCount: number;
|
|
105
|
+
format: string;
|
|
106
|
+
context?: OperationContext;
|
|
107
|
+
}
|
|
108
|
+
interface CompensationChangedEventPayload {
|
|
109
|
+
employee: {
|
|
110
|
+
id: ObjectId;
|
|
111
|
+
employeeId: string;
|
|
112
|
+
};
|
|
113
|
+
changeType: 'allowance_added' | 'allowance_removed' | 'deduction_added' | 'deduction_removed';
|
|
114
|
+
details: {
|
|
115
|
+
type: string;
|
|
116
|
+
amount: number;
|
|
117
|
+
};
|
|
118
|
+
organizationId: ObjectId;
|
|
119
|
+
context?: OperationContext;
|
|
120
|
+
}
|
|
121
|
+
interface MilestoneAchievedEventPayload {
|
|
122
|
+
employee: {
|
|
123
|
+
id: ObjectId;
|
|
124
|
+
employeeId: string;
|
|
125
|
+
name?: string;
|
|
126
|
+
};
|
|
127
|
+
milestone: {
|
|
128
|
+
type: 'tenure' | 'salary' | 'payments';
|
|
129
|
+
value: number;
|
|
130
|
+
message: string;
|
|
131
|
+
};
|
|
132
|
+
organizationId: ObjectId;
|
|
133
|
+
}
|
|
134
|
+
interface TaxWithheldEventPayload {
|
|
135
|
+
withholding: {
|
|
136
|
+
id: ObjectId;
|
|
137
|
+
taxType: string;
|
|
138
|
+
amount: number;
|
|
139
|
+
};
|
|
140
|
+
employee: {
|
|
141
|
+
id: ObjectId;
|
|
142
|
+
employeeId: string;
|
|
143
|
+
};
|
|
144
|
+
payrollRecord: {
|
|
145
|
+
id: ObjectId;
|
|
146
|
+
};
|
|
147
|
+
period: {
|
|
148
|
+
month: number;
|
|
149
|
+
year: number;
|
|
150
|
+
};
|
|
151
|
+
organizationId: ObjectId;
|
|
152
|
+
context?: OperationContext;
|
|
153
|
+
}
|
|
154
|
+
interface TaxPaidEventPayload {
|
|
155
|
+
withholdings: Array<{
|
|
156
|
+
id: ObjectId;
|
|
157
|
+
taxType: string;
|
|
158
|
+
amount: number;
|
|
159
|
+
}>;
|
|
160
|
+
transaction?: {
|
|
161
|
+
id: ObjectId;
|
|
162
|
+
amount: number;
|
|
163
|
+
};
|
|
164
|
+
totalAmount: number;
|
|
165
|
+
referenceNumber?: string;
|
|
166
|
+
paidAt: Date;
|
|
167
|
+
organizationId: ObjectId;
|
|
168
|
+
context?: OperationContext;
|
|
169
|
+
}
|
|
170
|
+
interface PayrollEventMap {
|
|
171
|
+
'employee:hired': EmployeeHiredEventPayload;
|
|
172
|
+
'employee:terminated': EmployeeTerminatedEventPayload;
|
|
173
|
+
'employee:rehired': EmployeeRehiredEventPayload;
|
|
174
|
+
'salary:updated': SalaryUpdatedEventPayload;
|
|
175
|
+
'salary:processed': SalaryProcessedEventPayload;
|
|
176
|
+
'salary:failed': SalaryFailedEventPayload;
|
|
177
|
+
'payroll:completed': PayrollCompletedEventPayload;
|
|
178
|
+
'payroll:exported': PayrollExportedEventPayload;
|
|
179
|
+
'compensation:changed': CompensationChangedEventPayload;
|
|
180
|
+
'milestone:achieved': MilestoneAchievedEventPayload;
|
|
181
|
+
'tax:withheld': TaxWithheldEventPayload;
|
|
182
|
+
'tax:paid': TaxPaidEventPayload;
|
|
183
|
+
}
|
|
184
|
+
type PayrollEventType = keyof PayrollEventMap;
|
|
185
|
+
type EventHandler<T> = (payload: T) => void | Promise<void>;
|
|
186
|
+
type PayrollEventHandler<K extends PayrollEventType> = EventHandler<PayrollEventMap[K]>;
|
|
187
|
+
declare class EventBus {
|
|
188
|
+
private handlers;
|
|
189
|
+
/**
|
|
190
|
+
* Register an event handler
|
|
191
|
+
*/
|
|
192
|
+
on<K extends PayrollEventType>(event: K, handler: PayrollEventHandler<K>): () => void;
|
|
193
|
+
/**
|
|
194
|
+
* Register a one-time event handler
|
|
195
|
+
*/
|
|
196
|
+
once<K extends PayrollEventType>(event: K, handler: PayrollEventHandler<K>): () => void;
|
|
197
|
+
/**
|
|
198
|
+
* Remove an event handler
|
|
199
|
+
*/
|
|
200
|
+
off<K extends PayrollEventType>(event: K, handler: PayrollEventHandler<K>): void;
|
|
201
|
+
/**
|
|
202
|
+
* Emit an event
|
|
203
|
+
*/
|
|
204
|
+
emit<K extends PayrollEventType>(event: K, payload: PayrollEventMap[K]): Promise<void>;
|
|
205
|
+
/**
|
|
206
|
+
* Emit event synchronously (fire-and-forget)
|
|
207
|
+
*/
|
|
208
|
+
emitSync<K extends PayrollEventType>(event: K, payload: PayrollEventMap[K]): void;
|
|
209
|
+
/**
|
|
210
|
+
* Remove all handlers for an event
|
|
211
|
+
*/
|
|
212
|
+
removeAllListeners(event?: PayrollEventType): void;
|
|
213
|
+
/**
|
|
214
|
+
* Get listener count for an event
|
|
215
|
+
*/
|
|
216
|
+
listenerCount(event: PayrollEventType): number;
|
|
217
|
+
/**
|
|
218
|
+
* Get all registered events
|
|
219
|
+
*/
|
|
220
|
+
eventNames(): PayrollEventType[];
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Get or create the default event bus
|
|
224
|
+
*/
|
|
225
|
+
declare function getEventBus(): EventBus;
|
|
226
|
+
/**
|
|
227
|
+
* Create a new event bus instance
|
|
228
|
+
*/
|
|
229
|
+
declare function createEventBus(): EventBus;
|
|
230
|
+
/**
|
|
231
|
+
* Reset the default event bus (for testing)
|
|
232
|
+
*/
|
|
233
|
+
declare function resetEventBus(): void;
|
|
234
|
+
/**
|
|
235
|
+
* Subscribe to employee hired events
|
|
236
|
+
*/
|
|
237
|
+
declare function onEmployeeHired(handler: PayrollEventHandler<'employee:hired'>): () => void;
|
|
238
|
+
/**
|
|
239
|
+
* Subscribe to salary processed events
|
|
240
|
+
*/
|
|
241
|
+
declare function onSalaryProcessed(handler: PayrollEventHandler<'salary:processed'>): () => void;
|
|
242
|
+
/**
|
|
243
|
+
* Subscribe to payroll completed events
|
|
244
|
+
*/
|
|
245
|
+
declare function onPayrollCompleted(handler: PayrollEventHandler<'payroll:completed'>): () => void;
|
|
246
|
+
/**
|
|
247
|
+
* Subscribe to milestone achieved events
|
|
248
|
+
*/
|
|
249
|
+
declare function onMilestoneAchieved(handler: PayrollEventHandler<'milestone:achieved'>): () => void;
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Webhook System
|
|
253
|
+
* Sends HTTP notifications when payroll events occur
|
|
254
|
+
*/
|
|
255
|
+
|
|
256
|
+
interface WebhookConfig {
|
|
257
|
+
url: string;
|
|
258
|
+
events: PayrollEventType[];
|
|
259
|
+
secret?: string;
|
|
260
|
+
headers?: Record<string, string>;
|
|
261
|
+
retries?: number;
|
|
262
|
+
timeout?: number;
|
|
263
|
+
}
|
|
264
|
+
interface WebhookDelivery {
|
|
265
|
+
id: string;
|
|
266
|
+
event: PayrollEventType;
|
|
267
|
+
url: string;
|
|
268
|
+
payload: unknown;
|
|
269
|
+
attempt: number;
|
|
270
|
+
status: 'pending' | 'sent' | 'failed';
|
|
271
|
+
response?: {
|
|
272
|
+
status: number;
|
|
273
|
+
body: string;
|
|
274
|
+
};
|
|
275
|
+
error?: string;
|
|
276
|
+
sentAt?: Date;
|
|
277
|
+
}
|
|
278
|
+
declare class WebhookManager {
|
|
279
|
+
private webhooks;
|
|
280
|
+
private deliveryLog;
|
|
281
|
+
/**
|
|
282
|
+
* Register a webhook
|
|
283
|
+
*/
|
|
284
|
+
register(config: WebhookConfig): void;
|
|
285
|
+
/**
|
|
286
|
+
* Remove a webhook
|
|
287
|
+
*/
|
|
288
|
+
unregister(url: string): void;
|
|
289
|
+
/**
|
|
290
|
+
* Send webhook for event
|
|
291
|
+
*/
|
|
292
|
+
send<K extends PayrollEventType>(event: K, payload: PayrollEventMap[K]): Promise<void>;
|
|
293
|
+
/**
|
|
294
|
+
* Deliver webhook with retries
|
|
295
|
+
*/
|
|
296
|
+
private deliver;
|
|
297
|
+
/**
|
|
298
|
+
* Generate HMAC signature for webhook
|
|
299
|
+
*/
|
|
300
|
+
private generateSignature;
|
|
301
|
+
/**
|
|
302
|
+
* Sleep for ms
|
|
303
|
+
*/
|
|
304
|
+
private sleep;
|
|
305
|
+
/**
|
|
306
|
+
* Get delivery log
|
|
307
|
+
*/
|
|
308
|
+
getDeliveries(options?: {
|
|
309
|
+
event?: PayrollEventType;
|
|
310
|
+
status?: WebhookDelivery['status'];
|
|
311
|
+
limit?: number;
|
|
312
|
+
}): WebhookDelivery[];
|
|
313
|
+
/**
|
|
314
|
+
* Clear delivery log
|
|
315
|
+
*/
|
|
316
|
+
clearLog(): void;
|
|
317
|
+
/**
|
|
318
|
+
* Get all registered webhooks
|
|
319
|
+
*/
|
|
320
|
+
getWebhooks(): WebhookConfig[];
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* @classytic/payroll - Configuration & Calculation Utilities
|
|
325
|
+
*
|
|
326
|
+
* DESIGN PRINCIPLES:
|
|
327
|
+
* 1. Accept data, don't manage it
|
|
328
|
+
* 2. Pure functions - easy to test, no side effects
|
|
329
|
+
* 3. Smart defaults that work out of the box
|
|
330
|
+
* 4. Override at operation time when needed
|
|
331
|
+
*
|
|
332
|
+
* The payroll package CALCULATES, it doesn't STORE calendars/holidays.
|
|
333
|
+
* Your app manages that data and passes it when needed.
|
|
334
|
+
*/
|
|
335
|
+
/** Work schedule configuration */
|
|
336
|
+
interface WorkSchedule$1 {
|
|
337
|
+
/** Working days (0=Sun, 1=Mon, ..., 6=Sat). Default: Mon-Fri */
|
|
338
|
+
workingDays: number[];
|
|
339
|
+
/** Hours per work day. Default: 8 */
|
|
340
|
+
hoursPerDay: number;
|
|
341
|
+
}
|
|
342
|
+
/** Options passed when processing payroll */
|
|
343
|
+
interface PayrollProcessingOptions {
|
|
344
|
+
/** Holidays in this period (from YOUR app's holiday model) */
|
|
345
|
+
holidays?: Date[];
|
|
346
|
+
/** Override work schedule for this operation */
|
|
347
|
+
workSchedule?: Partial<WorkSchedule$1>;
|
|
348
|
+
/** Skip tax calculation */
|
|
349
|
+
skipTax?: boolean;
|
|
350
|
+
/** Skip proration (pay full amount regardless of hire/termination date) */
|
|
351
|
+
skipProration?: boolean;
|
|
352
|
+
/** Skip attendance deduction */
|
|
353
|
+
skipAttendance?: boolean;
|
|
354
|
+
}
|
|
355
|
+
/** Working days calculation result */
|
|
356
|
+
interface WorkingDaysResult {
|
|
357
|
+
/** Total calendar days in period */
|
|
358
|
+
totalDays: number;
|
|
359
|
+
/** Working days (excluding weekends and holidays) */
|
|
360
|
+
workingDays: number;
|
|
361
|
+
/** Weekend days */
|
|
362
|
+
weekends: number;
|
|
363
|
+
/** Holiday count */
|
|
364
|
+
holidays: number;
|
|
365
|
+
}
|
|
366
|
+
/** Proration calculation result */
|
|
367
|
+
interface ProrationResult {
|
|
368
|
+
/** Proration ratio (0-1) */
|
|
369
|
+
ratio: number;
|
|
370
|
+
/** Reason for proration */
|
|
371
|
+
reason: 'full' | 'new_hire' | 'termination' | 'both';
|
|
372
|
+
/** Whether salary should be prorated */
|
|
373
|
+
isProrated: boolean;
|
|
374
|
+
}
|
|
375
|
+
/** Tax calculation result */
|
|
376
|
+
interface TaxResult {
|
|
377
|
+
/** Tax amount */
|
|
378
|
+
amount: number;
|
|
379
|
+
/** Effective tax rate */
|
|
380
|
+
effectiveRate: number;
|
|
381
|
+
}
|
|
382
|
+
/** Attendance data (from YOUR attendance system) */
|
|
383
|
+
interface AttendanceInput {
|
|
384
|
+
/** Expected work days in period */
|
|
385
|
+
expectedDays: number;
|
|
386
|
+
/** Actual days worked */
|
|
387
|
+
actualDays: number;
|
|
388
|
+
}
|
|
389
|
+
/** Complete salary calculation result */
|
|
390
|
+
interface SalaryCalculationResult {
|
|
391
|
+
/** Original base salary */
|
|
392
|
+
baseSalary: number;
|
|
393
|
+
/** Prorated base salary */
|
|
394
|
+
proratedBase: number;
|
|
395
|
+
/** Total allowances */
|
|
396
|
+
totalAllowances: number;
|
|
397
|
+
/** Total deductions (excluding tax) */
|
|
398
|
+
totalDeductions: number;
|
|
399
|
+
/** Attendance deduction */
|
|
400
|
+
attendanceDeduction: number;
|
|
401
|
+
/** Gross salary (prorated base + allowances) */
|
|
402
|
+
grossSalary: number;
|
|
403
|
+
/** Tax amount */
|
|
404
|
+
taxAmount: number;
|
|
405
|
+
/** Net salary (gross - all deductions - tax) */
|
|
406
|
+
netSalary: number;
|
|
407
|
+
/** Proration details */
|
|
408
|
+
proration: ProrationResult;
|
|
409
|
+
/** Working days details */
|
|
410
|
+
workingDays: WorkingDaysResult;
|
|
411
|
+
/** Itemized breakdown */
|
|
412
|
+
breakdown: {
|
|
413
|
+
allowances: Array<{
|
|
414
|
+
type: string;
|
|
415
|
+
amount: number;
|
|
416
|
+
taxable: boolean;
|
|
417
|
+
}>;
|
|
418
|
+
deductions: Array<{
|
|
419
|
+
type: string;
|
|
420
|
+
amount: number;
|
|
421
|
+
}>;
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Default tax brackets (US federal example)
|
|
426
|
+
* For multi-jurisdiction support, use the jurisdiction system instead
|
|
427
|
+
*/
|
|
428
|
+
declare const DEFAULT_TAX_BRACKETS: Array<{
|
|
429
|
+
min: number;
|
|
430
|
+
max: number;
|
|
431
|
+
rate: number;
|
|
432
|
+
}>;
|
|
433
|
+
declare const DEFAULT_WORK_SCHEDULE: WorkSchedule$1;
|
|
434
|
+
/**
|
|
435
|
+
* Count working days in a date range
|
|
436
|
+
*
|
|
437
|
+
* @example
|
|
438
|
+
* const result = countWorkingDays(
|
|
439
|
+
* new Date('2024-03-01'),
|
|
440
|
+
* new Date('2024-03-31'),
|
|
441
|
+
* { workingDays: [1,2,3,4,5], holidays: companyHolidays }
|
|
442
|
+
* );
|
|
443
|
+
*/
|
|
444
|
+
declare function countWorkingDays(startDate: Date, endDate: Date, options?: {
|
|
445
|
+
workingDays?: number[];
|
|
446
|
+
holidays?: Date[];
|
|
447
|
+
}): WorkingDaysResult;
|
|
448
|
+
/**
|
|
449
|
+
* Calculate proration ratio for partial months
|
|
450
|
+
*
|
|
451
|
+
* @example
|
|
452
|
+
* const proration = calculateProration(
|
|
453
|
+
* employee.hireDate,
|
|
454
|
+
* employee.terminationDate,
|
|
455
|
+
* periodStart,
|
|
456
|
+
* periodEnd
|
|
457
|
+
* );
|
|
458
|
+
*/
|
|
459
|
+
declare function calculateProration(hireDate: Date, terminationDate: Date | null | undefined, periodStart: Date, periodEnd: Date): ProrationResult;
|
|
460
|
+
/**
|
|
461
|
+
* Calculate attendance deduction
|
|
462
|
+
*
|
|
463
|
+
* @example
|
|
464
|
+
* const deduction = calculateAttendanceDeduction(22, 20, dailyRate);
|
|
465
|
+
*/
|
|
466
|
+
declare function calculateAttendanceDeduction(expectedDays: number, actualDays: number, dailyRate: number, maxDeductionPercent?: number): number;
|
|
467
|
+
/**
|
|
468
|
+
* Calculate complete salary breakdown
|
|
469
|
+
*
|
|
470
|
+
* This is the main function for salary calculation.
|
|
471
|
+
* Pass all data from YOUR app, get back complete breakdown.
|
|
472
|
+
*
|
|
473
|
+
* Note: Uses simple tax calculation. For multi-jurisdiction tax,
|
|
474
|
+
* use the jurisdiction system instead.
|
|
475
|
+
*
|
|
476
|
+
* @example
|
|
477
|
+
* const result = calculateSalaryBreakdown({
|
|
478
|
+
* baseSalary: 100000,
|
|
479
|
+
* hireDate: employee.hireDate,
|
|
480
|
+
* terminationDate: employee.terminationDate,
|
|
481
|
+
* periodStart: new Date('2024-03-01'),
|
|
482
|
+
* periodEnd: new Date('2024-03-31'),
|
|
483
|
+
* allowances: [{ type: 'housing', amount: 20000, taxable: true }],
|
|
484
|
+
* deductions: [{ type: 'provident_fund', amount: 5000 }],
|
|
485
|
+
* options: { holidays: companyHolidays },
|
|
486
|
+
* attendance: { expectedDays: 22, actualDays: 20 },
|
|
487
|
+
* });
|
|
488
|
+
*/
|
|
489
|
+
declare function calculateSalaryBreakdown(params: {
|
|
490
|
+
baseSalary: number;
|
|
491
|
+
hireDate: Date;
|
|
492
|
+
terminationDate?: Date | null;
|
|
493
|
+
periodStart: Date;
|
|
494
|
+
periodEnd: Date;
|
|
495
|
+
allowances?: Array<{
|
|
496
|
+
type: string;
|
|
497
|
+
amount: number;
|
|
498
|
+
taxable?: boolean;
|
|
499
|
+
}>;
|
|
500
|
+
deductions?: Array<{
|
|
501
|
+
type: string;
|
|
502
|
+
amount: number;
|
|
503
|
+
}>;
|
|
504
|
+
options?: PayrollProcessingOptions;
|
|
505
|
+
attendance?: AttendanceInput;
|
|
506
|
+
}): SalaryCalculationResult;
|
|
507
|
+
/**
|
|
508
|
+
* Get pay period dates for a given month
|
|
509
|
+
*
|
|
510
|
+
* @example
|
|
511
|
+
* const period = getPayPeriod(3, 2024); // March 2024
|
|
512
|
+
*/
|
|
513
|
+
declare function getPayPeriod(month: number, year: number, payDay?: number): {
|
|
514
|
+
startDate: Date;
|
|
515
|
+
endDate: Date;
|
|
516
|
+
payDate: Date;
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* @classytic/payroll - Plugin System
|
|
521
|
+
*
|
|
522
|
+
* Extensible plugin architecture for customization
|
|
523
|
+
* Follows patterns from popular libraries like Mongoose, Fastify
|
|
524
|
+
*/
|
|
525
|
+
|
|
526
|
+
interface PluginContext {
|
|
527
|
+
/** Payroll instance */
|
|
528
|
+
payroll: PayrollInstance;
|
|
529
|
+
/** Event bus for subscribing to events */
|
|
530
|
+
events: EventBus;
|
|
531
|
+
/** Logger instance */
|
|
532
|
+
logger: PluginLogger;
|
|
533
|
+
/** Configuration getter */
|
|
534
|
+
getConfig: <T>(key: string) => T | undefined;
|
|
535
|
+
/** Register a hook */
|
|
536
|
+
addHook: <K extends PayrollEventType>(event: K, handler: (payload: PayrollEventMap[K]) => void | Promise<void>) => () => void;
|
|
537
|
+
}
|
|
538
|
+
interface PluginLogger {
|
|
539
|
+
info(message: string, meta?: Record<string, unknown>): void;
|
|
540
|
+
error(message: string, meta?: Record<string, unknown>): void;
|
|
541
|
+
warn(message: string, meta?: Record<string, unknown>): void;
|
|
542
|
+
debug(message: string, meta?: Record<string, unknown>): void;
|
|
543
|
+
}
|
|
544
|
+
interface PluginHooks {
|
|
545
|
+
/** Called before employee is hired */
|
|
546
|
+
beforeHire?: (params: unknown) => void | Promise<void>;
|
|
547
|
+
/** Called after employee is hired */
|
|
548
|
+
afterHire?: (employee: unknown) => void | Promise<void>;
|
|
549
|
+
/** Called before salary is processed */
|
|
550
|
+
beforeProcessSalary?: (params: unknown) => void | Promise<void>;
|
|
551
|
+
/** Called after salary is processed */
|
|
552
|
+
afterProcessSalary?: (result: unknown) => void | Promise<void>;
|
|
553
|
+
/** Called before termination */
|
|
554
|
+
beforeTerminate?: (params: unknown) => void | Promise<void>;
|
|
555
|
+
/** Called after termination */
|
|
556
|
+
afterTerminate?: (employee: unknown) => void | Promise<void>;
|
|
557
|
+
/** Called on any error */
|
|
558
|
+
onError?: (error: Error, context: string) => void | Promise<void>;
|
|
559
|
+
}
|
|
560
|
+
interface PayrollPluginDefinition {
|
|
561
|
+
name: string;
|
|
562
|
+
version?: string;
|
|
563
|
+
hooks?: PluginHooks;
|
|
564
|
+
init?: (context: PluginContext) => void | Promise<void>;
|
|
565
|
+
destroy?: () => void | Promise<void>;
|
|
566
|
+
}
|
|
567
|
+
declare class PluginManager {
|
|
568
|
+
private context;
|
|
569
|
+
private plugins;
|
|
570
|
+
private hooks;
|
|
571
|
+
constructor(context: PluginContext);
|
|
572
|
+
/**
|
|
573
|
+
* Register a plugin
|
|
574
|
+
*/
|
|
575
|
+
register(plugin: PayrollPluginDefinition): Promise<void>;
|
|
576
|
+
/**
|
|
577
|
+
* Unregister a plugin
|
|
578
|
+
*/
|
|
579
|
+
unregister(name: string): Promise<void>;
|
|
580
|
+
/**
|
|
581
|
+
* Add a hook handler
|
|
582
|
+
*/
|
|
583
|
+
private addHook;
|
|
584
|
+
/**
|
|
585
|
+
* Execute hooks for a given event
|
|
586
|
+
*/
|
|
587
|
+
executeHooks<K extends keyof PluginHooks>(hookName: K, ...args: Parameters<NonNullable<PluginHooks[K]>>): Promise<void>;
|
|
588
|
+
/**
|
|
589
|
+
* Get registered plugin names
|
|
590
|
+
*/
|
|
591
|
+
getPluginNames(): string[];
|
|
592
|
+
/**
|
|
593
|
+
* Check if plugin is registered
|
|
594
|
+
*/
|
|
595
|
+
hasPlugin(name: string): boolean;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Define a plugin with type safety
|
|
599
|
+
*/
|
|
600
|
+
declare function definePlugin(definition: PayrollPluginDefinition): PayrollPluginDefinition;
|
|
601
|
+
/**
|
|
602
|
+
* Logging plugin - logs all payroll events
|
|
603
|
+
*/
|
|
604
|
+
declare const loggingPlugin: PayrollPluginDefinition;
|
|
605
|
+
/**
|
|
606
|
+
* Metrics plugin - collects payroll metrics
|
|
607
|
+
*/
|
|
608
|
+
declare const metricsPlugin: PayrollPluginDefinition;
|
|
609
|
+
/**
|
|
610
|
+
* Notification plugin - sends notifications for events
|
|
611
|
+
*/
|
|
612
|
+
interface NotificationPluginOptions {
|
|
613
|
+
onHired?: (employee: {
|
|
614
|
+
id: unknown;
|
|
615
|
+
name?: string;
|
|
616
|
+
}) => void | Promise<void>;
|
|
617
|
+
onTerminated?: (employee: {
|
|
618
|
+
id: unknown;
|
|
619
|
+
name?: string;
|
|
620
|
+
}) => void | Promise<void>;
|
|
621
|
+
onSalaryProcessed?: (details: {
|
|
622
|
+
employee: {
|
|
623
|
+
id: unknown;
|
|
624
|
+
name?: string;
|
|
625
|
+
};
|
|
626
|
+
amount: number;
|
|
627
|
+
}) => void | Promise<void>;
|
|
628
|
+
onMilestone?: (details: {
|
|
629
|
+
employee: {
|
|
630
|
+
id: unknown;
|
|
631
|
+
name?: string;
|
|
632
|
+
};
|
|
633
|
+
milestone: string;
|
|
634
|
+
}) => void | Promise<void>;
|
|
635
|
+
}
|
|
636
|
+
declare function createNotificationPlugin(options: NotificationPluginOptions): PayrollPluginDefinition;
|
|
637
|
+
declare const notificationPlugin: PayrollPluginDefinition;
|
|
638
|
+
|
|
639
|
+
/** Query filter type */
|
|
640
|
+
type FilterQuery<T> = {
|
|
641
|
+
[P in keyof T]?: T[P] | {
|
|
642
|
+
$in?: T[P][];
|
|
643
|
+
} | {
|
|
644
|
+
$ne?: T[P];
|
|
645
|
+
} | {
|
|
646
|
+
$gte?: T[P];
|
|
647
|
+
} | {
|
|
648
|
+
$lte?: T[P];
|
|
649
|
+
};
|
|
650
|
+
} & Record<string, unknown>;
|
|
651
|
+
/** Re-export mongoose ObjectId */
|
|
652
|
+
type ObjectId = Types.ObjectId;
|
|
653
|
+
/** ObjectId or string representation */
|
|
654
|
+
type ObjectIdLike = ObjectId | string;
|
|
655
|
+
/** Generic document type */
|
|
656
|
+
type AnyDocument = Document & Record<string, unknown>;
|
|
657
|
+
/** Generic model type */
|
|
658
|
+
type AnyModel = Model<AnyDocument>;
|
|
659
|
+
/** Deep partial type for nested objects */
|
|
660
|
+
type DeepPartial<T> = {
|
|
661
|
+
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
|
662
|
+
};
|
|
663
|
+
/** Nullable type helper */
|
|
664
|
+
type Nullable<T> = T | null;
|
|
665
|
+
/** Employment type */
|
|
666
|
+
type EmploymentType = 'full_time' | 'part_time' | 'contract' | 'intern' | 'consultant';
|
|
667
|
+
/** Employee status */
|
|
668
|
+
type EmployeeStatus = 'active' | 'on_leave' | 'suspended' | 'terminated';
|
|
669
|
+
/** Department type */
|
|
670
|
+
type Department = 'management' | 'training' | 'sales' | 'operations' | 'support' | 'hr' | 'maintenance' | 'marketing' | 'finance' | 'it';
|
|
671
|
+
/** Payment frequency */
|
|
672
|
+
type PaymentFrequency = 'monthly' | 'bi_weekly' | 'weekly' | 'hourly' | 'daily';
|
|
673
|
+
/** Payment method */
|
|
674
|
+
type PaymentMethod = 'bank' | 'cash' | 'check' | 'mobile' | 'bkash' | 'nagad' | 'rocket';
|
|
675
|
+
/** Allowance type */
|
|
676
|
+
type AllowanceType = 'housing' | 'transport' | 'meal' | 'mobile' | 'medical' | 'education' | 'bonus' | 'other';
|
|
677
|
+
/** Deduction type */
|
|
678
|
+
type DeductionType = 'tax' | 'loan' | 'advance' | 'provident_fund' | 'insurance' | 'absence' | 'other';
|
|
679
|
+
/** Payroll status */
|
|
680
|
+
type PayrollStatus = 'pending' | 'processing' | 'paid' | 'failed' | 'cancelled';
|
|
681
|
+
/** Termination reason */
|
|
682
|
+
type TerminationReason = 'resignation' | 'retirement' | 'termination' | 'contract_end' | 'mutual_agreement' | 'other';
|
|
683
|
+
/** HRM transaction category */
|
|
684
|
+
type HRMTransactionCategory = 'salary' | 'bonus' | 'commission' | 'overtime' | 'severance';
|
|
685
|
+
/** Salary band */
|
|
686
|
+
type SalaryBand = 'intern' | 'junior' | 'mid' | 'senior' | 'lead' | 'executive' | 'custom';
|
|
687
|
+
/** Organization role (app-defined) */
|
|
688
|
+
type OrgRole = string;
|
|
689
|
+
/** Leave type */
|
|
690
|
+
type LeaveType = 'annual' | 'sick' | 'unpaid' | 'maternity' | 'paternity' | 'bereavement' | 'compensatory' | 'other';
|
|
691
|
+
/** Leave request status */
|
|
692
|
+
type LeaveRequestStatus = 'pending' | 'approved' | 'rejected' | 'cancelled';
|
|
693
|
+
/** Data retention configuration */
|
|
694
|
+
interface DataRetentionConfig {
|
|
695
|
+
/** TTL for payroll records in seconds (default: 2 years) */
|
|
696
|
+
payrollRecordsTTL: number;
|
|
697
|
+
/** Days before TTL to warn (default: 30) */
|
|
698
|
+
exportWarningDays: number;
|
|
699
|
+
/** Archive records before deletion */
|
|
700
|
+
archiveBeforeDeletion: boolean;
|
|
701
|
+
}
|
|
702
|
+
/** Payroll configuration */
|
|
703
|
+
interface PayrollConfig {
|
|
704
|
+
/** Default currency code */
|
|
705
|
+
defaultCurrency: string;
|
|
706
|
+
/** Allow pro-rating for mid-month hires */
|
|
707
|
+
allowProRating: boolean;
|
|
708
|
+
/** Enable attendance integration */
|
|
709
|
+
attendanceIntegration: boolean;
|
|
710
|
+
/** Auto-apply deductions */
|
|
711
|
+
autoDeductions: boolean;
|
|
712
|
+
/** Enable overtime calculations */
|
|
713
|
+
overtimeEnabled: boolean;
|
|
714
|
+
/** Overtime multiplier (e.g., 1.5 for 150%) */
|
|
715
|
+
overtimeMultiplier: number;
|
|
716
|
+
}
|
|
717
|
+
/** Salary configuration */
|
|
718
|
+
interface SalaryConfig {
|
|
719
|
+
/** Minimum wage threshold */
|
|
720
|
+
minimumWage: number;
|
|
721
|
+
/** Maximum number of allowances */
|
|
722
|
+
maximumAllowances: number;
|
|
723
|
+
/** Maximum number of deductions */
|
|
724
|
+
maximumDeductions: number;
|
|
725
|
+
/** Default payment frequency */
|
|
726
|
+
defaultFrequency: PaymentFrequency;
|
|
727
|
+
}
|
|
728
|
+
/** Employment configuration */
|
|
729
|
+
interface EmploymentConfig {
|
|
730
|
+
/** Default probation period in months */
|
|
731
|
+
defaultProbationMonths: number;
|
|
732
|
+
/** Maximum probation period in months */
|
|
733
|
+
maxProbationMonths: number;
|
|
734
|
+
/** Allow re-hiring terminated employees */
|
|
735
|
+
allowReHiring: boolean;
|
|
736
|
+
/** Track employment history */
|
|
737
|
+
trackEmploymentHistory: boolean;
|
|
738
|
+
}
|
|
739
|
+
/** Employee identity mode - how employees are identified and looked up */
|
|
740
|
+
type EmployeeIdentityMode = 'userId' | 'employeeId' | 'email' | 'any';
|
|
741
|
+
/** Validation configuration */
|
|
742
|
+
interface ValidationConfig {
|
|
743
|
+
/** Require bank details for salary payment */
|
|
744
|
+
requireBankDetails: boolean;
|
|
745
|
+
/** Require userId for all employees (false = allow guest employees) */
|
|
746
|
+
requireUserId: boolean;
|
|
747
|
+
/** Primary identity mode for lookups */
|
|
748
|
+
identityMode: EmployeeIdentityMode;
|
|
749
|
+
/** Fallback modes if primary lookup fails */
|
|
750
|
+
identityFallbacks: EmployeeIdentityMode[];
|
|
751
|
+
}
|
|
752
|
+
/** Tax bracket definition */
|
|
753
|
+
interface TaxBracket {
|
|
754
|
+
/** Minimum income for bracket */
|
|
755
|
+
min: number;
|
|
756
|
+
/** Maximum income for bracket */
|
|
757
|
+
max: number;
|
|
758
|
+
/** Tax rate (0-1) */
|
|
759
|
+
rate: number;
|
|
760
|
+
}
|
|
761
|
+
/** Salary band range */
|
|
762
|
+
interface SalaryBandRange {
|
|
763
|
+
/** Minimum salary */
|
|
764
|
+
min: number;
|
|
765
|
+
/** Maximum salary */
|
|
766
|
+
max: number;
|
|
767
|
+
}
|
|
768
|
+
/** Role mapping configuration */
|
|
769
|
+
interface RoleMappingConfig {
|
|
770
|
+
/** Department to role mapping */
|
|
771
|
+
byDepartment: Record<string, OrgRole>;
|
|
772
|
+
/** Employment type to role mapping */
|
|
773
|
+
byEmploymentType: Record<string, OrgRole>;
|
|
774
|
+
/** Default role */
|
|
775
|
+
default: OrgRole;
|
|
776
|
+
}
|
|
777
|
+
/** Main HRM configuration */
|
|
778
|
+
interface HRMConfig {
|
|
779
|
+
/** Data retention settings */
|
|
780
|
+
dataRetention: DataRetentionConfig;
|
|
781
|
+
/** Payroll settings */
|
|
782
|
+
payroll: PayrollConfig;
|
|
783
|
+
/** Salary settings */
|
|
784
|
+
salary: SalaryConfig;
|
|
785
|
+
/** Employment settings */
|
|
786
|
+
employment: EmploymentConfig;
|
|
787
|
+
/** Validation settings */
|
|
788
|
+
validation: ValidationConfig;
|
|
789
|
+
}
|
|
790
|
+
/** Single-tenant configuration */
|
|
791
|
+
interface SingleTenantConfig {
|
|
792
|
+
/** Fixed organization ID (optional - will use default if not provided) */
|
|
793
|
+
organizationId?: ObjectIdLike;
|
|
794
|
+
/** Auto-inject organizationId if missing (default: true) */
|
|
795
|
+
autoInject?: boolean;
|
|
796
|
+
}
|
|
797
|
+
/** Main Payroll initialization config with strong generics */
|
|
798
|
+
interface PayrollInitConfig<TEmployee extends EmployeeDocument = EmployeeDocument, TPayrollRecord extends PayrollRecordDocument = PayrollRecordDocument, TTransaction extends AnyDocument = AnyDocument, TAttendance extends AnyDocument = AnyDocument> {
|
|
799
|
+
/** Employee model (required) - strongly typed */
|
|
800
|
+
EmployeeModel: Model<TEmployee>;
|
|
801
|
+
/** Payroll record model (required) - strongly typed */
|
|
802
|
+
PayrollRecordModel: Model<TPayrollRecord>;
|
|
803
|
+
/** Transaction model (required) - strongly typed */
|
|
804
|
+
TransactionModel: Model<TTransaction>;
|
|
805
|
+
/** Attendance model (optional, for integration) - strongly typed */
|
|
806
|
+
AttendanceModel?: Model<TAttendance> | null;
|
|
807
|
+
/** Single-tenant configuration */
|
|
808
|
+
singleTenant?: SingleTenantConfig | null;
|
|
809
|
+
/** Custom logger */
|
|
810
|
+
logger?: Logger;
|
|
811
|
+
/** Custom HRM config overrides */
|
|
812
|
+
config?: DeepPartial<HRMConfig>;
|
|
813
|
+
}
|
|
814
|
+
/** User reference for audit */
|
|
815
|
+
interface UserReference {
|
|
816
|
+
userId?: ObjectId;
|
|
817
|
+
name?: string;
|
|
818
|
+
role?: string;
|
|
819
|
+
}
|
|
820
|
+
/** Bank details */
|
|
821
|
+
interface BankDetails {
|
|
822
|
+
accountName?: string;
|
|
823
|
+
accountNumber?: string;
|
|
824
|
+
bankName?: string;
|
|
825
|
+
branchName?: string;
|
|
826
|
+
routingNumber?: string;
|
|
827
|
+
}
|
|
828
|
+
/** Allowance entry */
|
|
829
|
+
interface Allowance {
|
|
830
|
+
type: AllowanceType;
|
|
831
|
+
name?: string;
|
|
832
|
+
amount: number;
|
|
833
|
+
/** Whether amount is percentage of base salary */
|
|
834
|
+
isPercentage?: boolean;
|
|
835
|
+
/** Percentage value if isPercentage is true */
|
|
836
|
+
value?: number;
|
|
837
|
+
taxable?: boolean;
|
|
838
|
+
recurring?: boolean;
|
|
839
|
+
effectiveFrom?: Date;
|
|
840
|
+
effectiveTo?: Date | null;
|
|
841
|
+
}
|
|
842
|
+
/** Deduction entry */
|
|
843
|
+
interface Deduction {
|
|
844
|
+
type: DeductionType;
|
|
845
|
+
name?: string;
|
|
846
|
+
amount: number;
|
|
847
|
+
/** Whether amount is percentage of base salary */
|
|
848
|
+
isPercentage?: boolean;
|
|
849
|
+
/** Percentage value if isPercentage is true */
|
|
850
|
+
value?: number;
|
|
851
|
+
auto?: boolean;
|
|
852
|
+
recurring?: boolean;
|
|
853
|
+
effectiveFrom?: Date;
|
|
854
|
+
effectiveTo?: Date | null;
|
|
855
|
+
description?: string;
|
|
856
|
+
}
|
|
857
|
+
/** Compensation structure */
|
|
858
|
+
interface Compensation {
|
|
859
|
+
/** Base salary amount */
|
|
860
|
+
baseAmount: number;
|
|
861
|
+
/** Payment frequency */
|
|
862
|
+
frequency: PaymentFrequency;
|
|
863
|
+
/** Currency code */
|
|
864
|
+
currency: string;
|
|
865
|
+
/** Allowances array */
|
|
866
|
+
allowances: Allowance[];
|
|
867
|
+
/** Deductions array */
|
|
868
|
+
deductions: Deduction[];
|
|
869
|
+
/** Calculated gross salary */
|
|
870
|
+
grossSalary?: number;
|
|
871
|
+
/** Calculated net salary */
|
|
872
|
+
netSalary?: number;
|
|
873
|
+
/** When compensation became effective */
|
|
874
|
+
effectiveFrom?: Date;
|
|
875
|
+
/** Last modified timestamp */
|
|
876
|
+
lastModified?: Date;
|
|
877
|
+
}
|
|
878
|
+
/** Work schedule */
|
|
879
|
+
interface WorkSchedule {
|
|
880
|
+
hoursPerWeek?: number;
|
|
881
|
+
hoursPerDay?: number;
|
|
882
|
+
/** Working days (0=Sunday, 6=Saturday) */
|
|
883
|
+
workingDays?: number[];
|
|
884
|
+
shiftStart?: string;
|
|
885
|
+
shiftEnd?: string;
|
|
886
|
+
}
|
|
887
|
+
/** Employment history entry */
|
|
888
|
+
interface EmploymentHistoryEntry {
|
|
889
|
+
hireDate: Date;
|
|
890
|
+
terminationDate: Date;
|
|
891
|
+
reason?: TerminationReason;
|
|
892
|
+
finalSalary?: number;
|
|
893
|
+
position?: string;
|
|
894
|
+
department?: string;
|
|
895
|
+
notes?: string;
|
|
896
|
+
createdAt?: Date;
|
|
897
|
+
updatedAt?: Date;
|
|
898
|
+
}
|
|
899
|
+
/** Payroll stats (pre-calculated) */
|
|
900
|
+
interface PayrollStats {
|
|
901
|
+
totalPaid: number;
|
|
902
|
+
lastPaymentDate?: Date | null;
|
|
903
|
+
nextPaymentDate?: Date | null;
|
|
904
|
+
paymentsThisYear: number;
|
|
905
|
+
averageMonthly: number;
|
|
906
|
+
updatedAt?: Date;
|
|
907
|
+
}
|
|
908
|
+
/** Employee document structure */
|
|
909
|
+
interface EmployeeDocument extends Document {
|
|
910
|
+
_id: ObjectId;
|
|
911
|
+
/**
|
|
912
|
+
* User reference (optional - guest employees don't have user accounts)
|
|
913
|
+
* In real Mongoose usage this can be either:
|
|
914
|
+
* - an ObjectId
|
|
915
|
+
* - a populated user document containing at least `_id`
|
|
916
|
+
* - undefined (guest employee)
|
|
917
|
+
*/
|
|
918
|
+
userId?: ObjectId | {
|
|
919
|
+
_id: ObjectId;
|
|
920
|
+
name?: string;
|
|
921
|
+
email?: string;
|
|
922
|
+
phone?: string;
|
|
923
|
+
};
|
|
924
|
+
/** Email for guest employees (when userId is not present) */
|
|
925
|
+
email?: string;
|
|
926
|
+
organizationId: ObjectId;
|
|
927
|
+
employeeId: string;
|
|
928
|
+
employmentType: EmploymentType;
|
|
929
|
+
status: EmployeeStatus;
|
|
930
|
+
department?: Department;
|
|
931
|
+
position: string;
|
|
932
|
+
hireDate: Date;
|
|
933
|
+
terminationDate?: Date | null;
|
|
934
|
+
probationEndDate?: Date | null;
|
|
935
|
+
employmentHistory: EmploymentHistoryEntry[];
|
|
936
|
+
compensation: Compensation;
|
|
937
|
+
workSchedule?: WorkSchedule;
|
|
938
|
+
bankDetails?: BankDetails;
|
|
939
|
+
payrollStats: PayrollStats;
|
|
940
|
+
notes?: string;
|
|
941
|
+
createdAt?: Date;
|
|
942
|
+
updatedAt?: Date;
|
|
943
|
+
save(options?: {
|
|
944
|
+
session?: ClientSession;
|
|
945
|
+
}): Promise<this>;
|
|
946
|
+
toObject(): Record<string, unknown>;
|
|
947
|
+
}
|
|
948
|
+
/** Payroll period */
|
|
949
|
+
interface PayrollPeriod {
|
|
950
|
+
month: number;
|
|
951
|
+
year: number;
|
|
952
|
+
startDate: Date;
|
|
953
|
+
endDate: Date;
|
|
954
|
+
payDate: Date;
|
|
955
|
+
}
|
|
956
|
+
/** Payroll breakdown */
|
|
957
|
+
interface PayrollBreakdown {
|
|
958
|
+
baseAmount: number;
|
|
959
|
+
allowances: Array<{
|
|
960
|
+
type: string;
|
|
961
|
+
amount: number;
|
|
962
|
+
taxable?: boolean;
|
|
963
|
+
}>;
|
|
964
|
+
deductions: Array<{
|
|
965
|
+
type: string;
|
|
966
|
+
amount: number;
|
|
967
|
+
description?: string;
|
|
968
|
+
}>;
|
|
969
|
+
grossSalary: number;
|
|
970
|
+
netSalary: number;
|
|
971
|
+
/** Taxable amount (base + taxable allowances) */
|
|
972
|
+
taxableAmount?: number;
|
|
973
|
+
/** Calculated tax amount */
|
|
974
|
+
taxAmount?: number;
|
|
975
|
+
workingDays?: number;
|
|
976
|
+
actualDays?: number;
|
|
977
|
+
proRatedAmount?: number;
|
|
978
|
+
attendanceDeduction?: number;
|
|
979
|
+
overtimeAmount?: number;
|
|
980
|
+
bonusAmount?: number;
|
|
981
|
+
}
|
|
982
|
+
/** Payroll correction entry */
|
|
983
|
+
interface PayrollCorrection {
|
|
984
|
+
previousAmount: number;
|
|
985
|
+
newAmount: number;
|
|
986
|
+
reason: string;
|
|
987
|
+
correctedBy: ObjectId;
|
|
988
|
+
correctedAt: Date;
|
|
989
|
+
}
|
|
990
|
+
/** Payroll record document */
|
|
991
|
+
interface PayrollRecordDocument extends Document {
|
|
992
|
+
_id: ObjectId;
|
|
993
|
+
organizationId: ObjectId;
|
|
994
|
+
employeeId: ObjectId;
|
|
995
|
+
userId?: ObjectId;
|
|
996
|
+
period: PayrollPeriod;
|
|
997
|
+
breakdown: PayrollBreakdown;
|
|
998
|
+
transactionId?: ObjectId | null;
|
|
999
|
+
status: PayrollStatus;
|
|
1000
|
+
paidAt?: Date | null;
|
|
1001
|
+
processedAt?: Date | null;
|
|
1002
|
+
paymentMethod?: PaymentMethod;
|
|
1003
|
+
metadata?: Record<string, unknown>;
|
|
1004
|
+
processedBy?: ObjectId;
|
|
1005
|
+
notes?: string;
|
|
1006
|
+
payslipUrl?: string;
|
|
1007
|
+
exported: boolean;
|
|
1008
|
+
exportedAt?: Date | null;
|
|
1009
|
+
corrections?: PayrollCorrection[];
|
|
1010
|
+
createdAt?: Date;
|
|
1011
|
+
updatedAt?: Date;
|
|
1012
|
+
save(options?: {
|
|
1013
|
+
session?: ClientSession;
|
|
1014
|
+
}): Promise<this>;
|
|
1015
|
+
toObject(): Record<string, unknown>;
|
|
1016
|
+
}
|
|
1017
|
+
/** Base operation context */
|
|
1018
|
+
interface OperationContext {
|
|
1019
|
+
/** User performing the operation */
|
|
1020
|
+
userId?: ObjectIdLike;
|
|
1021
|
+
/** User name */
|
|
1022
|
+
userName?: string;
|
|
1023
|
+
/** User role */
|
|
1024
|
+
userRole?: string;
|
|
1025
|
+
/** Organization ID (auto-injected in single-tenant mode) */
|
|
1026
|
+
organizationId?: ObjectIdLike;
|
|
1027
|
+
/** MongoDB session for transactions */
|
|
1028
|
+
session?: ClientSession;
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
1031
|
+
* Base parameters for all employee operations
|
|
1032
|
+
* Enforces multi-tenant isolation and supports dual identity
|
|
1033
|
+
*/
|
|
1034
|
+
/**
|
|
1035
|
+
* Employee ID resolution mode
|
|
1036
|
+
*
|
|
1037
|
+
* @example
|
|
1038
|
+
* // Auto-detect (recommended)
|
|
1039
|
+
* { employeeId: 'EMP-001' } // Treated as business ID
|
|
1040
|
+
*
|
|
1041
|
+
* @example
|
|
1042
|
+
* // Force business ID (for 24-hex IDs that look like ObjectId)
|
|
1043
|
+
* { employeeId: '000000000000000000000001', employeeIdMode: 'businessId' }
|
|
1044
|
+
*
|
|
1045
|
+
* @example
|
|
1046
|
+
* // Force ObjectId lookup
|
|
1047
|
+
* { employeeId: employee._id, employeeIdMode: 'objectId' }
|
|
1048
|
+
*/
|
|
1049
|
+
type EmployeeIdMode = 'auto' | 'objectId' | 'businessId';
|
|
1050
|
+
interface EmployeeOperationParams {
|
|
1051
|
+
/**
|
|
1052
|
+
* Employee identifier (supports both formats):
|
|
1053
|
+
* - ObjectId: employee._id (MongoDB document ID)
|
|
1054
|
+
* - String: "EMP-001" (business identifier)
|
|
1055
|
+
*/
|
|
1056
|
+
employeeId: ObjectIdLike | string;
|
|
1057
|
+
/**
|
|
1058
|
+
* How to interpret employeeId (explicit control for edge cases)
|
|
1059
|
+
*
|
|
1060
|
+
* @default 'auto' - Smart detection
|
|
1061
|
+
*
|
|
1062
|
+
* Explicit mode hint for employeeId disambiguation
|
|
1063
|
+
*
|
|
1064
|
+
* - 'auto' (default): Auto-detect via isValidObjectId()
|
|
1065
|
+
* - 'objectId': Force treat as MongoDB _id (ObjectId)
|
|
1066
|
+
* - 'businessId': Force treat as business employeeId string
|
|
1067
|
+
*
|
|
1068
|
+
* Use 'businessId' if your employeeIds are 24-hex strings like
|
|
1069
|
+
* "507f1f77bcf86cd799439011" to prevent ObjectId collision.
|
|
1070
|
+
*
|
|
1071
|
+
* @default 'auto'
|
|
1072
|
+
* @since v2.3.0
|
|
1073
|
+
*
|
|
1074
|
+
* @example
|
|
1075
|
+
* // Force treat as business ID (prevents ObjectId collision)
|
|
1076
|
+
* await payroll.processSalary({
|
|
1077
|
+
* employeeId: "507f1f77bcf86cd799439011",
|
|
1078
|
+
* employeeIdMode: 'businessId',
|
|
1079
|
+
* organizationId: org._id,
|
|
1080
|
+
* month: 3, year: 2024
|
|
1081
|
+
* });
|
|
1082
|
+
*/
|
|
1083
|
+
employeeIdMode?: EmployeeIdMode;
|
|
1084
|
+
/**
|
|
1085
|
+
* Organization ID for multi-tenant isolation
|
|
1086
|
+
*
|
|
1087
|
+
* **Multi-tenant mode:** REQUIRED (enforced at runtime)
|
|
1088
|
+
* **Single-tenant mode:** Optional (auto-injected if autoInject=true)
|
|
1089
|
+
*
|
|
1090
|
+
* **Resolution Priority:**
|
|
1091
|
+
* 1. This explicit value (highest)
|
|
1092
|
+
* 2. context.organizationId (from middleware/auth)
|
|
1093
|
+
* 3. Single-tenant config (if autoInject enabled)
|
|
1094
|
+
* 4. Error thrown (if none found in multi-tenant mode)
|
|
1095
|
+
*
|
|
1096
|
+
* @example
|
|
1097
|
+
* // Multi-tenant: explicit organizationId
|
|
1098
|
+
* await payroll.processSalary({
|
|
1099
|
+
* employeeId: emp._id,
|
|
1100
|
+
* organizationId: org._id, // Required
|
|
1101
|
+
* month: 3, year: 2024
|
|
1102
|
+
* });
|
|
1103
|
+
*
|
|
1104
|
+
* @example
|
|
1105
|
+
* // Multi-tenant: via context
|
|
1106
|
+
* await payroll.processSalary({
|
|
1107
|
+
* employeeId: emp._id,
|
|
1108
|
+
* month: 3, year: 2024,
|
|
1109
|
+
* context: { organizationId: org._id } // From middleware
|
|
1110
|
+
* });
|
|
1111
|
+
*
|
|
1112
|
+
* @example
|
|
1113
|
+
* // Single-tenant: auto-injected
|
|
1114
|
+
* const payroll = createPayrollInstance()
|
|
1115
|
+
* .forSingleTenant({ organizationId: myOrg._id, autoInject: true })
|
|
1116
|
+
* .build();
|
|
1117
|
+
*
|
|
1118
|
+
* await payroll.processSalary({
|
|
1119
|
+
* employeeId: emp._id,
|
|
1120
|
+
* // organizationId auto-injected ✨
|
|
1121
|
+
* month: 3, year: 2024
|
|
1122
|
+
* });
|
|
1123
|
+
*/
|
|
1124
|
+
organizationId?: ObjectIdLike;
|
|
1125
|
+
/**
|
|
1126
|
+
* Operation context (auth, session, metadata)
|
|
1127
|
+
*/
|
|
1128
|
+
context?: OperationContext;
|
|
1129
|
+
}
|
|
1130
|
+
/** Hire employee parameters */
|
|
1131
|
+
interface HireEmployeeParams {
|
|
1132
|
+
/** User ID (optional - for guest employees without user account) */
|
|
1133
|
+
userId?: ObjectIdLike;
|
|
1134
|
+
/** Organization ID (optional in single-tenant mode - auto-injected) */
|
|
1135
|
+
organizationId?: ObjectIdLike;
|
|
1136
|
+
/** Employment details */
|
|
1137
|
+
employment: {
|
|
1138
|
+
employeeId?: string;
|
|
1139
|
+
/** Email for guest employees (when userId is not provided) */
|
|
1140
|
+
email?: string;
|
|
1141
|
+
type?: EmploymentType;
|
|
1142
|
+
department?: Department | string;
|
|
1143
|
+
position: string;
|
|
1144
|
+
hireDate?: Date;
|
|
1145
|
+
probationMonths?: number;
|
|
1146
|
+
workSchedule?: WorkSchedule;
|
|
1147
|
+
};
|
|
1148
|
+
/** Compensation details */
|
|
1149
|
+
compensation: {
|
|
1150
|
+
baseAmount: number;
|
|
1151
|
+
frequency?: PaymentFrequency;
|
|
1152
|
+
currency?: string;
|
|
1153
|
+
allowances?: Array<Partial<Allowance>>;
|
|
1154
|
+
deductions?: Array<Partial<Deduction>>;
|
|
1155
|
+
};
|
|
1156
|
+
/** Bank details */
|
|
1157
|
+
bankDetails?: BankDetails;
|
|
1158
|
+
/** Operation context */
|
|
1159
|
+
context?: OperationContext;
|
|
1160
|
+
}
|
|
1161
|
+
/** Update employment parameters */
|
|
1162
|
+
interface UpdateEmploymentParams extends EmployeeOperationParams {
|
|
1163
|
+
/** Fields to update */
|
|
1164
|
+
updates: {
|
|
1165
|
+
department?: Department;
|
|
1166
|
+
position?: string;
|
|
1167
|
+
employmentType?: EmploymentType;
|
|
1168
|
+
status?: EmployeeStatus;
|
|
1169
|
+
workSchedule?: WorkSchedule;
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
/** Terminate employee parameters */
|
|
1173
|
+
interface TerminateEmployeeParams extends EmployeeOperationParams {
|
|
1174
|
+
/** Termination date */
|
|
1175
|
+
terminationDate?: Date;
|
|
1176
|
+
/** Termination reason */
|
|
1177
|
+
reason?: TerminationReason;
|
|
1178
|
+
/** Notes */
|
|
1179
|
+
notes?: string;
|
|
1180
|
+
}
|
|
1181
|
+
/** Re-hire employee parameters */
|
|
1182
|
+
interface ReHireEmployeeParams extends EmployeeOperationParams {
|
|
1183
|
+
/** New hire date */
|
|
1184
|
+
hireDate?: Date;
|
|
1185
|
+
/** New position */
|
|
1186
|
+
position?: string;
|
|
1187
|
+
/** New department */
|
|
1188
|
+
department?: Department;
|
|
1189
|
+
/** New compensation */
|
|
1190
|
+
compensation?: DeepPartial<Compensation>;
|
|
1191
|
+
}
|
|
1192
|
+
/** List employees parameters */
|
|
1193
|
+
interface ListEmployeesParams {
|
|
1194
|
+
/** Organization ID */
|
|
1195
|
+
organizationId: ObjectIdLike;
|
|
1196
|
+
/** Filters */
|
|
1197
|
+
filters?: {
|
|
1198
|
+
status?: EmployeeStatus;
|
|
1199
|
+
department?: Department;
|
|
1200
|
+
employmentType?: EmploymentType;
|
|
1201
|
+
minSalary?: number;
|
|
1202
|
+
maxSalary?: number;
|
|
1203
|
+
};
|
|
1204
|
+
/** Pagination */
|
|
1205
|
+
pagination?: {
|
|
1206
|
+
page?: number;
|
|
1207
|
+
limit?: number;
|
|
1208
|
+
sort?: Record<string, 1 | -1>;
|
|
1209
|
+
};
|
|
1210
|
+
}
|
|
1211
|
+
/** Update salary parameters */
|
|
1212
|
+
interface UpdateSalaryParams extends EmployeeOperationParams {
|
|
1213
|
+
/** Compensation updates */
|
|
1214
|
+
compensation: {
|
|
1215
|
+
baseAmount?: number;
|
|
1216
|
+
frequency?: PaymentFrequency;
|
|
1217
|
+
currency?: string;
|
|
1218
|
+
};
|
|
1219
|
+
/** Effective from date */
|
|
1220
|
+
effectiveFrom?: Date;
|
|
1221
|
+
}
|
|
1222
|
+
/** Add allowance parameters */
|
|
1223
|
+
interface AddAllowanceParams extends EmployeeOperationParams {
|
|
1224
|
+
/** Allowance type */
|
|
1225
|
+
type: AllowanceType;
|
|
1226
|
+
/** Amount (fixed or ignored if isPercentage is true) */
|
|
1227
|
+
amount: number;
|
|
1228
|
+
/** Whether amount is percentage of base salary */
|
|
1229
|
+
isPercentage?: boolean;
|
|
1230
|
+
/** Percentage value if isPercentage is true */
|
|
1231
|
+
value?: number;
|
|
1232
|
+
/** Is taxable */
|
|
1233
|
+
taxable?: boolean;
|
|
1234
|
+
/** Is recurring */
|
|
1235
|
+
recurring?: boolean;
|
|
1236
|
+
/** Effective from */
|
|
1237
|
+
effectiveFrom?: Date;
|
|
1238
|
+
/** Effective to */
|
|
1239
|
+
effectiveTo?: Date | null;
|
|
1240
|
+
}
|
|
1241
|
+
/** Remove allowance parameters */
|
|
1242
|
+
interface RemoveAllowanceParams extends EmployeeOperationParams {
|
|
1243
|
+
/** Allowance type to remove */
|
|
1244
|
+
type: AllowanceType;
|
|
1245
|
+
}
|
|
1246
|
+
/** Add deduction parameters */
|
|
1247
|
+
interface AddDeductionParams extends EmployeeOperationParams {
|
|
1248
|
+
/** Deduction type */
|
|
1249
|
+
type: DeductionType;
|
|
1250
|
+
/** Amount (fixed or ignored if isPercentage is true) */
|
|
1251
|
+
amount: number;
|
|
1252
|
+
/** Whether amount is percentage of base salary */
|
|
1253
|
+
isPercentage?: boolean;
|
|
1254
|
+
/** Percentage value if isPercentage is true */
|
|
1255
|
+
value?: number;
|
|
1256
|
+
/** Auto-deduct from salary */
|
|
1257
|
+
auto?: boolean;
|
|
1258
|
+
/** Is recurring */
|
|
1259
|
+
recurring?: boolean;
|
|
1260
|
+
/** Description */
|
|
1261
|
+
description?: string;
|
|
1262
|
+
/** Effective from */
|
|
1263
|
+
effectiveFrom?: Date;
|
|
1264
|
+
/** Effective to */
|
|
1265
|
+
effectiveTo?: Date | null;
|
|
1266
|
+
}
|
|
1267
|
+
/** Remove deduction parameters */
|
|
1268
|
+
interface RemoveDeductionParams extends EmployeeOperationParams {
|
|
1269
|
+
/** Deduction type to remove */
|
|
1270
|
+
type: DeductionType;
|
|
1271
|
+
}
|
|
1272
|
+
/** Update bank details parameters */
|
|
1273
|
+
interface UpdateBankDetailsParams extends EmployeeOperationParams {
|
|
1274
|
+
/** Bank details */
|
|
1275
|
+
bankDetails: BankDetails;
|
|
1276
|
+
}
|
|
1277
|
+
/** Process salary parameters */
|
|
1278
|
+
interface ProcessSalaryParams extends EmployeeOperationParams {
|
|
1279
|
+
/** Month (1-12) */
|
|
1280
|
+
month: number;
|
|
1281
|
+
/** Year */
|
|
1282
|
+
year: number;
|
|
1283
|
+
/** Payment date */
|
|
1284
|
+
paymentDate?: Date;
|
|
1285
|
+
/** Payment method */
|
|
1286
|
+
paymentMethod?: PaymentMethod;
|
|
1287
|
+
/**
|
|
1288
|
+
* Idempotency key (Stripe-style)
|
|
1289
|
+
* If provided, duplicate calls with same key return cached result
|
|
1290
|
+
* Auto-generated if not provided: `payroll:{orgId}:{empId}:{year}-{month}`
|
|
1291
|
+
*/
|
|
1292
|
+
idempotencyKey?: string;
|
|
1293
|
+
/**
|
|
1294
|
+
* Optional attendance override (useful when embedding into any HRM system).
|
|
1295
|
+
* If provided, payroll will use this instead of querying AttendanceModel.
|
|
1296
|
+
*/
|
|
1297
|
+
attendance?: AttendanceInput | null;
|
|
1298
|
+
/**
|
|
1299
|
+
* Optional processing options (holidays/work schedule/skip flags).
|
|
1300
|
+
* This aligns with the pure functions in `@classytic/payroll/core`.
|
|
1301
|
+
*/
|
|
1302
|
+
options?: PayrollProcessingOptions;
|
|
1303
|
+
}
|
|
1304
|
+
/** Bulk payroll progress information */
|
|
1305
|
+
interface BulkPayrollProgress {
|
|
1306
|
+
/** Number of employees processed so far */
|
|
1307
|
+
processed: number;
|
|
1308
|
+
/** Total number of employees to process */
|
|
1309
|
+
total: number;
|
|
1310
|
+
/** Number of successful processings */
|
|
1311
|
+
successful: number;
|
|
1312
|
+
/** Number of failed processings */
|
|
1313
|
+
failed: number;
|
|
1314
|
+
/** Currently processing employee ID (optional) */
|
|
1315
|
+
currentEmployee?: string;
|
|
1316
|
+
/** Completion percentage (0-100) */
|
|
1317
|
+
percentage?: number;
|
|
1318
|
+
}
|
|
1319
|
+
/** Process bulk payroll parameters */
|
|
1320
|
+
interface ProcessBulkPayrollParams {
|
|
1321
|
+
/** Organization ID */
|
|
1322
|
+
organizationId: ObjectIdLike;
|
|
1323
|
+
/** Month (1-12) */
|
|
1324
|
+
month: number;
|
|
1325
|
+
/** Year */
|
|
1326
|
+
year: number;
|
|
1327
|
+
/** Specific employee IDs (empty = all active) */
|
|
1328
|
+
employeeIds?: ObjectIdLike[];
|
|
1329
|
+
/** Payment date */
|
|
1330
|
+
paymentDate?: Date;
|
|
1331
|
+
/** Payment method */
|
|
1332
|
+
paymentMethod?: PaymentMethod;
|
|
1333
|
+
/**
|
|
1334
|
+
* Optional processing options (holidays/work schedule/skip flags).
|
|
1335
|
+
* Passed through to each employee's salary processing.
|
|
1336
|
+
*/
|
|
1337
|
+
options?: PayrollProcessingOptions;
|
|
1338
|
+
/** Operation context */
|
|
1339
|
+
context?: OperationContext;
|
|
1340
|
+
/**
|
|
1341
|
+
* Progress callback - called after each employee is processed
|
|
1342
|
+
* Useful for updating job queue progress, UI updates, etc.
|
|
1343
|
+
* @example
|
|
1344
|
+
* onProgress: async (progress) => {
|
|
1345
|
+
* await Job.findByIdAndUpdate(jobId, { progress });
|
|
1346
|
+
* }
|
|
1347
|
+
*/
|
|
1348
|
+
onProgress?: (progress: BulkPayrollProgress) => void | Promise<void>;
|
|
1349
|
+
/**
|
|
1350
|
+
* Cancellation signal - check signal.aborted to allow graceful cancellation
|
|
1351
|
+
* @example
|
|
1352
|
+
* const controller = new AbortController();
|
|
1353
|
+
* processBulkPayroll({ ..., signal: controller.signal });
|
|
1354
|
+
* // Later: controller.abort();
|
|
1355
|
+
*/
|
|
1356
|
+
signal?: AbortSignal;
|
|
1357
|
+
/**
|
|
1358
|
+
* Batch size - number of employees to process before pausing (default: 10)
|
|
1359
|
+
* Helps prevent resource exhaustion and allows event loop to process other tasks
|
|
1360
|
+
*/
|
|
1361
|
+
batchSize?: number;
|
|
1362
|
+
/**
|
|
1363
|
+
* Batch delay in milliseconds - pause between batches (default: 0)
|
|
1364
|
+
* Useful for rate limiting or preventing database connection pool exhaustion
|
|
1365
|
+
*/
|
|
1366
|
+
batchDelay?: number;
|
|
1367
|
+
/**
|
|
1368
|
+
* Concurrency - number of employees to process in parallel (default: 1)
|
|
1369
|
+
* - 1: Sequential processing (safest, default)
|
|
1370
|
+
* - 2-5: Moderate parallelism (faster, uses more resources)
|
|
1371
|
+
* - 10+: High parallelism (fastest, requires robust infrastructure)
|
|
1372
|
+
*/
|
|
1373
|
+
concurrency?: number;
|
|
1374
|
+
/**
|
|
1375
|
+
* Use cursor-based streaming for processing (default: auto)
|
|
1376
|
+
* - false: Load all into memory (fast for <10k employees)
|
|
1377
|
+
* - true: Stream via cursor (scales to millions, constant memory)
|
|
1378
|
+
* - undefined/auto: Automatically use streaming for >10k employees
|
|
1379
|
+
*/
|
|
1380
|
+
useStreaming?: boolean;
|
|
1381
|
+
}
|
|
1382
|
+
/** Payroll history parameters */
|
|
1383
|
+
interface PayrollHistoryParams {
|
|
1384
|
+
/** Employee identifier (ObjectId _id or string business ID like "EMP-001") */
|
|
1385
|
+
employeeId?: ObjectIdLike | string;
|
|
1386
|
+
/** Explicit mode hint for employeeId disambiguation @since v2.3.0 */
|
|
1387
|
+
employeeIdMode?: EmployeeIdMode;
|
|
1388
|
+
/** Organization ID */
|
|
1389
|
+
organizationId?: ObjectIdLike;
|
|
1390
|
+
/** Month filter */
|
|
1391
|
+
month?: number;
|
|
1392
|
+
/** Year filter */
|
|
1393
|
+
year?: number;
|
|
1394
|
+
/** Status filter */
|
|
1395
|
+
status?: PayrollStatus;
|
|
1396
|
+
/** Pagination */
|
|
1397
|
+
pagination?: {
|
|
1398
|
+
page?: number;
|
|
1399
|
+
limit?: number;
|
|
1400
|
+
sort?: Record<string, 1 | -1>;
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
1403
|
+
/** Payroll summary parameters */
|
|
1404
|
+
interface PayrollSummaryParams {
|
|
1405
|
+
/** Organization ID */
|
|
1406
|
+
organizationId: ObjectIdLike;
|
|
1407
|
+
/** Month */
|
|
1408
|
+
month?: number;
|
|
1409
|
+
/** Year */
|
|
1410
|
+
year?: number;
|
|
1411
|
+
}
|
|
1412
|
+
/** Export payroll parameters */
|
|
1413
|
+
interface ExportPayrollParams {
|
|
1414
|
+
/** Organization ID */
|
|
1415
|
+
organizationId: ObjectIdLike;
|
|
1416
|
+
/** Start date */
|
|
1417
|
+
startDate: Date;
|
|
1418
|
+
/** End date */
|
|
1419
|
+
endDate: Date;
|
|
1420
|
+
/** Export format */
|
|
1421
|
+
format?: 'json' | 'csv';
|
|
1422
|
+
}
|
|
1423
|
+
/** Process salary result (generic for best DX) */
|
|
1424
|
+
interface ProcessSalaryResult<TEmployee extends EmployeeDocument = EmployeeDocument, TPayrollRecord extends PayrollRecordDocument = PayrollRecordDocument, TTransaction extends AnyDocument = AnyDocument> {
|
|
1425
|
+
payrollRecord: TPayrollRecord;
|
|
1426
|
+
transaction: TTransaction;
|
|
1427
|
+
employee: TEmployee;
|
|
1428
|
+
}
|
|
1429
|
+
/** Bulk payroll result */
|
|
1430
|
+
interface BulkPayrollResult {
|
|
1431
|
+
successful: Array<{
|
|
1432
|
+
employeeId: string;
|
|
1433
|
+
amount: number;
|
|
1434
|
+
transactionId: ObjectId;
|
|
1435
|
+
}>;
|
|
1436
|
+
failed: Array<{
|
|
1437
|
+
employeeId: string;
|
|
1438
|
+
error: string;
|
|
1439
|
+
}>;
|
|
1440
|
+
total: number;
|
|
1441
|
+
}
|
|
1442
|
+
/** Payroll summary result */
|
|
1443
|
+
interface PayrollSummaryResult {
|
|
1444
|
+
totalGross: number;
|
|
1445
|
+
totalNet: number;
|
|
1446
|
+
totalDeductions: number;
|
|
1447
|
+
employeeCount: number;
|
|
1448
|
+
paidCount: number;
|
|
1449
|
+
pendingCount: number;
|
|
1450
|
+
}
|
|
1451
|
+
/** Tax calculation result */
|
|
1452
|
+
interface TaxCalculationResult {
|
|
1453
|
+
gross: number;
|
|
1454
|
+
tax: number;
|
|
1455
|
+
net: number;
|
|
1456
|
+
}
|
|
1457
|
+
/** Compensation breakdown result */
|
|
1458
|
+
interface CompensationBreakdownResult {
|
|
1459
|
+
baseAmount: number;
|
|
1460
|
+
allowances: Array<Allowance & {
|
|
1461
|
+
calculatedAmount: number;
|
|
1462
|
+
}>;
|
|
1463
|
+
deductions: Array<Deduction & {
|
|
1464
|
+
calculatedAmount: number;
|
|
1465
|
+
}>;
|
|
1466
|
+
grossAmount: number;
|
|
1467
|
+
netAmount: number;
|
|
1468
|
+
}
|
|
1469
|
+
/**
|
|
1470
|
+
* Payroll instance interface (public surface) used for plugin typing.
|
|
1471
|
+
* This matches the actual `Payroll` class and keeps generics flowing.
|
|
1472
|
+
*/
|
|
1473
|
+
interface PayrollInstance<TEmployee extends EmployeeDocument = EmployeeDocument, TPayrollRecord extends PayrollRecordDocument = PayrollRecordDocument, TTransaction extends AnyDocument = AnyDocument, TAttendance extends AnyDocument = AnyDocument> {
|
|
1474
|
+
/** Check if initialized */
|
|
1475
|
+
isInitialized(): boolean;
|
|
1476
|
+
/** Register a plugin */
|
|
1477
|
+
use(plugin: PayrollPluginDefinition): Promise<this>;
|
|
1478
|
+
/** Subscribe to typed payroll events */
|
|
1479
|
+
on<K extends PayrollEventType>(event: K, handler: (payload: PayrollEventMap[K]) => void | Promise<void>): () => void;
|
|
1480
|
+
/** Register webhook (Stripe-style) */
|
|
1481
|
+
registerWebhook(config: WebhookConfig): void;
|
|
1482
|
+
/** Unregister webhook */
|
|
1483
|
+
unregisterWebhook(url: string): void;
|
|
1484
|
+
/** Get webhook delivery log */
|
|
1485
|
+
getWebhookDeliveries(options?: {
|
|
1486
|
+
event?: PayrollEventType;
|
|
1487
|
+
status?: 'pending' | 'sent' | 'failed';
|
|
1488
|
+
limit?: number;
|
|
1489
|
+
}): WebhookDelivery[];
|
|
1490
|
+
hire(params: HireEmployeeParams): Promise<TEmployee>;
|
|
1491
|
+
getEmployee(params: {
|
|
1492
|
+
employeeId: ObjectIdLike;
|
|
1493
|
+
populateUser?: boolean;
|
|
1494
|
+
session?: ClientSession;
|
|
1495
|
+
}): Promise<TEmployee>;
|
|
1496
|
+
updateEmployment(params: UpdateEmploymentParams): Promise<TEmployee>;
|
|
1497
|
+
terminate(params: TerminateEmployeeParams): Promise<TEmployee>;
|
|
1498
|
+
reHire(params: ReHireEmployeeParams): Promise<TEmployee>;
|
|
1499
|
+
listEmployees(params: ListEmployeesParams): Promise<{
|
|
1500
|
+
docs: TEmployee[];
|
|
1501
|
+
totalDocs: number;
|
|
1502
|
+
page: number;
|
|
1503
|
+
limit: number;
|
|
1504
|
+
}>;
|
|
1505
|
+
updateSalary(params: UpdateSalaryParams): Promise<TEmployee>;
|
|
1506
|
+
addAllowance(params: AddAllowanceParams): Promise<TEmployee>;
|
|
1507
|
+
removeAllowance(params: RemoveAllowanceParams): Promise<TEmployee>;
|
|
1508
|
+
addDeduction(params: AddDeductionParams): Promise<TEmployee>;
|
|
1509
|
+
removeDeduction(params: RemoveDeductionParams): Promise<TEmployee>;
|
|
1510
|
+
updateBankDetails(params: UpdateBankDetailsParams): Promise<TEmployee>;
|
|
1511
|
+
processSalary(params: ProcessSalaryParams): Promise<ProcessSalaryResult<TEmployee, TPayrollRecord, TTransaction>>;
|
|
1512
|
+
processBulkPayroll(params: ProcessBulkPayrollParams): Promise<BulkPayrollResult>;
|
|
1513
|
+
payrollHistory(params: PayrollHistoryParams): Promise<TPayrollRecord[]>;
|
|
1514
|
+
payrollSummary(params: PayrollSummaryParams): Promise<PayrollSummaryResult>;
|
|
1515
|
+
exportPayroll(params: ExportPayrollParams): Promise<TPayrollRecord[]>;
|
|
1516
|
+
/** Extended properties from plugins */
|
|
1517
|
+
[key: string]: unknown;
|
|
1518
|
+
}
|
|
1519
|
+
/**
|
|
1520
|
+
* @deprecated Use `PayrollPluginDefinition` from `@classytic/payroll/core`.
|
|
1521
|
+
* This legacy plugin shape is kept for compatibility with older code.
|
|
1522
|
+
*/
|
|
1523
|
+
interface PayrollPlugin {
|
|
1524
|
+
name: string;
|
|
1525
|
+
apply(payroll: PayrollInstance): void;
|
|
1526
|
+
}
|
|
1527
|
+
/** Plugin function signature */
|
|
1528
|
+
type PluginFunction = (payroll: PayrollInstance) => void;
|
|
1529
|
+
/** Plugin type (object or function) */
|
|
1530
|
+
type PluginType = PayrollPlugin | PluginFunction;
|
|
1531
|
+
/** Event names */
|
|
1532
|
+
type PayrollEvent = 'employee:hired' | 'employee:terminated' | 'employee:rehired' | 'salary:updated' | 'salary:processed' | 'salary:failed' | 'payroll:completed' | 'payroll:exported' | 'compensation:changed' | 'milestone:achieved';
|
|
1533
|
+
/** Event payload base */
|
|
1534
|
+
interface EventPayloadBase {
|
|
1535
|
+
type: PayrollEvent;
|
|
1536
|
+
timestamp: Date;
|
|
1537
|
+
}
|
|
1538
|
+
/** Employee hired event */
|
|
1539
|
+
interface EmployeeHiredEvent extends EventPayloadBase {
|
|
1540
|
+
type: 'employee:hired';
|
|
1541
|
+
data: {
|
|
1542
|
+
employee: {
|
|
1543
|
+
id: ObjectId;
|
|
1544
|
+
employeeId: string;
|
|
1545
|
+
position: string;
|
|
1546
|
+
department?: string;
|
|
1547
|
+
};
|
|
1548
|
+
organizationId: ObjectId;
|
|
1549
|
+
context?: OperationContext;
|
|
1550
|
+
};
|
|
1551
|
+
}
|
|
1552
|
+
/** Salary processed event */
|
|
1553
|
+
interface SalaryProcessedEvent extends EventPayloadBase {
|
|
1554
|
+
type: 'salary:processed';
|
|
1555
|
+
data: {
|
|
1556
|
+
employee: {
|
|
1557
|
+
id: ObjectId;
|
|
1558
|
+
employeeId: string;
|
|
1559
|
+
name?: string;
|
|
1560
|
+
};
|
|
1561
|
+
payroll: {
|
|
1562
|
+
id: ObjectId;
|
|
1563
|
+
period: {
|
|
1564
|
+
month: number;
|
|
1565
|
+
year: number;
|
|
1566
|
+
};
|
|
1567
|
+
amount: number;
|
|
1568
|
+
};
|
|
1569
|
+
transactionId: ObjectId;
|
|
1570
|
+
context?: OperationContext;
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1573
|
+
/** All event payloads union */
|
|
1574
|
+
type EventPayload = EmployeeHiredEvent | SalaryProcessedEvent;
|
|
1575
|
+
/** Logger interface */
|
|
1576
|
+
interface Logger {
|
|
1577
|
+
info(message: string, meta?: Record<string, unknown>): void;
|
|
1578
|
+
error(message: string, meta?: Record<string, unknown>): void;
|
|
1579
|
+
warn(message: string, meta?: Record<string, unknown>): void;
|
|
1580
|
+
debug(message: string, meta?: Record<string, unknown>): void;
|
|
1581
|
+
}
|
|
1582
|
+
/** Error codes */
|
|
1583
|
+
type ErrorCode = 'PAYROLL_ERROR' | 'NOT_INITIALIZED' | 'EMPLOYEE_NOT_FOUND' | 'INVALID_EMPLOYEE' | 'DUPLICATE_PAYROLL' | 'VALIDATION_ERROR' | 'EMPLOYEE_TERMINATED' | 'ALREADY_PROCESSED' | 'NOT_ELIGIBLE';
|
|
1584
|
+
/** HTTP error with status code */
|
|
1585
|
+
interface HttpError extends Error {
|
|
1586
|
+
code: ErrorCode;
|
|
1587
|
+
status: number;
|
|
1588
|
+
context?: Record<string, unknown>;
|
|
1589
|
+
timestamp: Date;
|
|
1590
|
+
}
|
|
1591
|
+
/** Pro-rating calculation result */
|
|
1592
|
+
interface ProRatingResult {
|
|
1593
|
+
isProRated: boolean;
|
|
1594
|
+
totalDays: number;
|
|
1595
|
+
actualDays: number;
|
|
1596
|
+
ratio: number;
|
|
1597
|
+
}
|
|
1598
|
+
/** Pay period info */
|
|
1599
|
+
interface PayPeriodInfo {
|
|
1600
|
+
month: number;
|
|
1601
|
+
year: number;
|
|
1602
|
+
startDate: Date;
|
|
1603
|
+
endDate: Date;
|
|
1604
|
+
}
|
|
1605
|
+
/** Employee validation result */
|
|
1606
|
+
interface EmployeeValidationResult {
|
|
1607
|
+
valid: boolean;
|
|
1608
|
+
errors: string[];
|
|
1609
|
+
}
|
|
1610
|
+
/** Query builder options */
|
|
1611
|
+
interface QueryOptions {
|
|
1612
|
+
session?: ClientSession;
|
|
1613
|
+
lean?: boolean;
|
|
1614
|
+
}
|
|
1615
|
+
/**
|
|
1616
|
+
* Base employee interface that Payroll expects
|
|
1617
|
+
* Extend this in your application
|
|
1618
|
+
*/
|
|
1619
|
+
interface PayrollEmployee {
|
|
1620
|
+
_id: ObjectId;
|
|
1621
|
+
userId: ObjectId;
|
|
1622
|
+
organizationId: ObjectId;
|
|
1623
|
+
employeeId: string;
|
|
1624
|
+
status: EmployeeStatus;
|
|
1625
|
+
compensation: Compensation;
|
|
1626
|
+
payrollStats?: PayrollStats;
|
|
1627
|
+
bankDetails?: BankDetails;
|
|
1628
|
+
}
|
|
1629
|
+
/**
|
|
1630
|
+
* Employee model with Payroll fields applied
|
|
1631
|
+
* Use this to type your employee model
|
|
1632
|
+
*/
|
|
1633
|
+
type WithPayroll<TEmployee> = TEmployee & {
|
|
1634
|
+
compensation: Compensation;
|
|
1635
|
+
payrollStats: PayrollStats;
|
|
1636
|
+
employmentHistory: EmploymentHistoryEntry[];
|
|
1637
|
+
};
|
|
1638
|
+
/** Leave balance entry (embedded in Employee) */
|
|
1639
|
+
interface LeaveBalance {
|
|
1640
|
+
/** Leave type */
|
|
1641
|
+
type: LeaveType;
|
|
1642
|
+
/** Allocated days for the year */
|
|
1643
|
+
allocated: number;
|
|
1644
|
+
/** Used days */
|
|
1645
|
+
used: number;
|
|
1646
|
+
/** Pending days (requested but not yet approved) */
|
|
1647
|
+
pending: number;
|
|
1648
|
+
/** Days carried over from previous year */
|
|
1649
|
+
carriedOver: number;
|
|
1650
|
+
/** When carried-over days expire */
|
|
1651
|
+
expiresAt?: Date | null;
|
|
1652
|
+
/** Year this balance applies to */
|
|
1653
|
+
year: number;
|
|
1654
|
+
}
|
|
1655
|
+
/** Leave request document */
|
|
1656
|
+
interface LeaveRequestDocument extends Document {
|
|
1657
|
+
_id: ObjectId;
|
|
1658
|
+
organizationId?: ObjectId;
|
|
1659
|
+
employeeId: ObjectId;
|
|
1660
|
+
userId?: ObjectId;
|
|
1661
|
+
type: LeaveType;
|
|
1662
|
+
startDate: Date;
|
|
1663
|
+
endDate: Date;
|
|
1664
|
+
days: number;
|
|
1665
|
+
halfDay?: boolean;
|
|
1666
|
+
reason?: string;
|
|
1667
|
+
status: LeaveRequestStatus;
|
|
1668
|
+
reviewedBy?: ObjectId | null;
|
|
1669
|
+
reviewedAt?: Date | null;
|
|
1670
|
+
reviewNotes?: string;
|
|
1671
|
+
attachments?: string[];
|
|
1672
|
+
metadata?: Record<string, unknown>;
|
|
1673
|
+
createdAt?: Date;
|
|
1674
|
+
updatedAt?: Date;
|
|
1675
|
+
save(options?: {
|
|
1676
|
+
session?: ClientSession;
|
|
1677
|
+
}): Promise<this>;
|
|
1678
|
+
toObject(): Record<string, unknown>;
|
|
1679
|
+
}
|
|
1680
|
+
/** Request leave input */
|
|
1681
|
+
interface RequestLeaveInput {
|
|
1682
|
+
type: LeaveType;
|
|
1683
|
+
startDate: Date;
|
|
1684
|
+
endDate: Date;
|
|
1685
|
+
halfDay?: boolean;
|
|
1686
|
+
reason?: string;
|
|
1687
|
+
attachments?: string[];
|
|
1688
|
+
}
|
|
1689
|
+
/** Review leave request input */
|
|
1690
|
+
interface ReviewLeaveRequestInput {
|
|
1691
|
+
requestId: ObjectIdLike;
|
|
1692
|
+
action: 'approve' | 'reject';
|
|
1693
|
+
notes?: string;
|
|
1694
|
+
}
|
|
1695
|
+
/** Leave history filters */
|
|
1696
|
+
interface LeaveHistoryFilters {
|
|
1697
|
+
type?: LeaveType;
|
|
1698
|
+
status?: LeaveRequestStatus;
|
|
1699
|
+
startDate?: Date;
|
|
1700
|
+
endDate?: Date;
|
|
1701
|
+
year?: number;
|
|
1702
|
+
}
|
|
1703
|
+
/** Accrue leave options */
|
|
1704
|
+
interface AccrueLeaveOptions {
|
|
1705
|
+
type?: LeaveType;
|
|
1706
|
+
amount?: number;
|
|
1707
|
+
proRate?: boolean;
|
|
1708
|
+
asOfDate?: Date;
|
|
1709
|
+
}
|
|
1710
|
+
/** Reset annual leave options */
|
|
1711
|
+
interface ResetAnnualLeaveOptions {
|
|
1712
|
+
year?: number;
|
|
1713
|
+
carryOverLimit?: number;
|
|
1714
|
+
leaveTypes?: LeaveType[];
|
|
1715
|
+
}
|
|
1716
|
+
/** Leave summary result */
|
|
1717
|
+
interface LeaveSummaryResult {
|
|
1718
|
+
year: number;
|
|
1719
|
+
balances: LeaveBalance[];
|
|
1720
|
+
totalAllocated: number;
|
|
1721
|
+
totalUsed: number;
|
|
1722
|
+
totalPending: number;
|
|
1723
|
+
totalAvailable: number;
|
|
1724
|
+
byType: Record<LeaveType, {
|
|
1725
|
+
allocated: number;
|
|
1726
|
+
used: number;
|
|
1727
|
+
pending: number;
|
|
1728
|
+
available: number;
|
|
1729
|
+
}>;
|
|
1730
|
+
}
|
|
1731
|
+
/** Leave initialization config */
|
|
1732
|
+
interface LeaveInitConfig {
|
|
1733
|
+
/** Default leave allocations by type */
|
|
1734
|
+
defaultAllocations?: Partial<Record<LeaveType, number>>;
|
|
1735
|
+
/** Whether to pro-rate for mid-year hires */
|
|
1736
|
+
proRateNewHires?: boolean;
|
|
1737
|
+
/** Fiscal year start month (1-12, default: 1 for January) */
|
|
1738
|
+
fiscalYearStartMonth?: number;
|
|
1739
|
+
/** Maximum carry-over days by type */
|
|
1740
|
+
maxCarryOver?: Partial<Record<LeaveType, number>>;
|
|
1741
|
+
}
|
|
1742
|
+
/** Working days calculation options */
|
|
1743
|
+
interface WorkingDaysOptions {
|
|
1744
|
+
/** Working days of week (0=Sunday, 6=Saturday). Default: [1,2,3,4,5] */
|
|
1745
|
+
workingDays?: number[];
|
|
1746
|
+
/** Holiday dates to exclude */
|
|
1747
|
+
holidays?: Date[];
|
|
1748
|
+
/** Include end date in calculation (default: true) */
|
|
1749
|
+
includeEndDate?: boolean;
|
|
1750
|
+
}
|
|
1751
|
+
/** Tax types supported by the system */
|
|
1752
|
+
type TaxType = 'income_tax' | 'social_security' | 'health_insurance' | 'pension' | 'employment_insurance' | 'local_tax' | 'other';
|
|
1753
|
+
/** Tax withholding status */
|
|
1754
|
+
type TaxStatus = 'pending' | 'submitted' | 'paid';
|
|
1755
|
+
/** Tax withholding document */
|
|
1756
|
+
interface TaxWithholdingDocument extends Document {
|
|
1757
|
+
_id: ObjectId;
|
|
1758
|
+
organizationId: ObjectId;
|
|
1759
|
+
employeeId: ObjectId;
|
|
1760
|
+
userId?: ObjectId;
|
|
1761
|
+
payrollRecordId: ObjectId;
|
|
1762
|
+
transactionId: ObjectId;
|
|
1763
|
+
period: PayrollPeriod;
|
|
1764
|
+
amount: number;
|
|
1765
|
+
currency: string;
|
|
1766
|
+
taxType: TaxType;
|
|
1767
|
+
taxRate: number;
|
|
1768
|
+
taxableAmount: number;
|
|
1769
|
+
status: TaxStatus;
|
|
1770
|
+
submittedAt?: Date;
|
|
1771
|
+
paidAt?: Date;
|
|
1772
|
+
governmentTransactionId?: ObjectId;
|
|
1773
|
+
referenceNumber?: string;
|
|
1774
|
+
notes?: string;
|
|
1775
|
+
metadata?: Record<string, unknown>;
|
|
1776
|
+
createdAt?: Date;
|
|
1777
|
+
updatedAt?: Date;
|
|
1778
|
+
markAsSubmitted(submittedAt?: Date): void;
|
|
1779
|
+
markAsPaid(transactionId?: ObjectId, referenceNumber?: string, paidAt?: Date): void;
|
|
1780
|
+
save(options?: {
|
|
1781
|
+
session?: ClientSession;
|
|
1782
|
+
}): Promise<this>;
|
|
1783
|
+
toObject(): Record<string, unknown>;
|
|
1784
|
+
}
|
|
1785
|
+
/** Parameters for querying pending tax withholdings */
|
|
1786
|
+
interface GetPendingTaxParams {
|
|
1787
|
+
organizationId: ObjectIdLike;
|
|
1788
|
+
fromPeriod?: {
|
|
1789
|
+
month: number;
|
|
1790
|
+
year: number;
|
|
1791
|
+
};
|
|
1792
|
+
toPeriod?: {
|
|
1793
|
+
month: number;
|
|
1794
|
+
year: number;
|
|
1795
|
+
};
|
|
1796
|
+
taxType?: TaxType;
|
|
1797
|
+
employeeId?: ObjectIdLike;
|
|
1798
|
+
}
|
|
1799
|
+
/** Parameters for tax summary aggregation */
|
|
1800
|
+
interface TaxSummaryParams {
|
|
1801
|
+
organizationId: ObjectIdLike;
|
|
1802
|
+
fromPeriod: {
|
|
1803
|
+
month: number;
|
|
1804
|
+
year: number;
|
|
1805
|
+
};
|
|
1806
|
+
toPeriod: {
|
|
1807
|
+
month: number;
|
|
1808
|
+
year: number;
|
|
1809
|
+
};
|
|
1810
|
+
groupBy?: 'type' | 'period' | 'employee';
|
|
1811
|
+
}
|
|
1812
|
+
/** Tax summary grouped by type */
|
|
1813
|
+
interface TaxSummaryByType {
|
|
1814
|
+
taxType: TaxType;
|
|
1815
|
+
totalAmount: number;
|
|
1816
|
+
count: number;
|
|
1817
|
+
withholdingIds: ObjectId[];
|
|
1818
|
+
}
|
|
1819
|
+
/** Tax summary result */
|
|
1820
|
+
interface TaxSummaryResult {
|
|
1821
|
+
totalAmount: number;
|
|
1822
|
+
count: number;
|
|
1823
|
+
byType: TaxSummaryByType[];
|
|
1824
|
+
period: {
|
|
1825
|
+
fromMonth: number;
|
|
1826
|
+
fromYear: number;
|
|
1827
|
+
toMonth: number;
|
|
1828
|
+
toYear: number;
|
|
1829
|
+
};
|
|
1830
|
+
}
|
|
1831
|
+
/** Parameters for marking tax withholdings as paid */
|
|
1832
|
+
interface MarkTaxPaidParams {
|
|
1833
|
+
organizationId: ObjectIdLike;
|
|
1834
|
+
withholdingIds: ObjectIdLike[];
|
|
1835
|
+
createTransaction?: boolean;
|
|
1836
|
+
referenceNumber?: string;
|
|
1837
|
+
paidAt?: Date;
|
|
1838
|
+
notes?: string;
|
|
1839
|
+
context?: OperationContext;
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
export { getEventBus as $, type AnyDocument as A, type BulkPayrollResult as B, type Logger as C, type DeepPartial as D, type EmployeeDocument as E, type EmploymentType as F, type GetPendingTaxParams as G, type HireEmployeeParams as H, type Department as I, type WorkSchedule as J, type PaymentFrequency as K, type ListEmployeesParams as L, type MarkTaxPaidParams as M, type Allowance as N, type ObjectIdLike as O, type PayrollRecordDocument as P, type Deduction as Q, type ReHireEmployeeParams as R, type SingleTenantConfig as S, type TerminateEmployeeParams as T, type UpdateEmploymentParams as U, type BankDetails as V, type WebhookConfig as W, type Compensation as X, type TerminationReason as Y, EventBus as Z, createEventBus as _, type PayrollInstance as a, type ErrorCode as a$, resetEventBus as a0, onEmployeeHired as a1, onSalaryProcessed as a2, onPayrollCompleted as a3, onMilestoneAchieved as a4, type PayrollEventHandler as a5, type EmployeeHiredEventPayload as a6, type EmployeeTerminatedEventPayload as a7, type EmployeeRehiredEventPayload as a8, type SalaryUpdatedEventPayload as a9, countWorkingDays as aA, calculateProration as aB, calculateAttendanceDeduction as aC, calculateSalaryBreakdown as aD, getPayPeriod as aE, type LeaveType as aF, type WorkingDaysOptions as aG, type LeaveBalance as aH, type LeaveSummaryResult as aI, type LeaveInitConfig as aJ, type EmployeeStatus as aK, type PayrollPeriod as aL, type PayrollBreakdown as aM, type PaymentMethod as aN, type CompensationBreakdownResult as aO, type AnyModel as aP, type ObjectId as aQ, type TaxType as aR, type TaxStatus as aS, type PayPeriodInfo as aT, type ProRatingResult as aU, type TaxCalculationResult as aV, type EmployeeValidationResult as aW, type PayrollStatus as aX, type LeaveRequestStatus as aY, type OrgRole as aZ, type HttpError as a_, type SalaryProcessedEventPayload as aa, type SalaryFailedEventPayload as ab, type PayrollCompletedEventPayload as ac, type PayrollExportedEventPayload as ad, type CompensationChangedEventPayload as ae, type MilestoneAchievedEventPayload as af, WebhookManager as ag, PluginManager as ah, definePlugin as ai, loggingPlugin as aj, metricsPlugin as ak, notificationPlugin as al, createNotificationPlugin as am, type PluginContext as an, type PluginLogger as ao, type PluginHooks as ap, type NotificationPluginOptions as aq, type WorkSchedule$1 as ar, type PayrollProcessingOptions as as, type WorkingDaysResult as at, type ProrationResult as au, type TaxResult as av, type AttendanceInput as aw, type SalaryCalculationResult as ax, DEFAULT_WORK_SCHEDULE as ay, DEFAULT_TAX_BRACKETS as az, type PayrollInitConfig as b, type Nullable as b0, type FilterQuery as b1, type DataRetentionConfig as b2, type PayrollConfig as b3, type SalaryConfig as b4, type EmploymentConfig as b5, type ValidationConfig as b6, type EmployeeIdMode as b7, type TaxBracket as b8, type SalaryBandRange as b9, type WithPayroll as bA, type TaxSummaryByType as bB, type RoleMappingConfig as ba, type PayrollStats as bb, type PayrollCorrection as bc, type EmploymentHistoryEntry as bd, type UserReference as be, type AllowanceType as bf, type DeductionType as bg, type SalaryBand as bh, type HRMTransactionCategory as bi, type RequestLeaveInput as bj, type ReviewLeaveRequestInput as bk, type LeaveHistoryFilters as bl, type AccrueLeaveOptions as bm, type ResetAnnualLeaveOptions as bn, type EmployeeOperationParams as bo, type BulkPayrollProgress as bp, type PayrollPlugin as bq, type PluginFunction as br, type PluginType as bs, type PayrollEvent as bt, type EventPayloadBase as bu, type EmployeeHiredEvent as bv, type SalaryProcessedEvent as bw, type EventPayload as bx, type QueryOptions as by, type PayrollEmployee as bz, type PayrollPluginDefinition as c, type PayrollEventMap as d, type PayrollEventType as e, type WebhookDelivery as f, type OperationContext as g, type EmployeeIdentityMode as h, type UpdateSalaryParams as i, type AddAllowanceParams as j, type RemoveAllowanceParams as k, type AddDeductionParams as l, type RemoveDeductionParams as m, type UpdateBankDetailsParams as n, type ProcessSalaryParams as o, type ProcessSalaryResult as p, type ProcessBulkPayrollParams as q, type PayrollHistoryParams as r, type PayrollSummaryParams as s, type PayrollSummaryResult as t, type ExportPayrollParams as u, type TaxWithholdingDocument as v, type TaxSummaryParams as w, type TaxSummaryResult as x, type LeaveRequestDocument as y, type HRMConfig as z };
|