@classytic/payroll 1.0.0 → 2.7.5

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.
Files changed (40) hide show
  1. package/README.md +525 -574
  2. package/dist/calculators/index.d.ts +300 -0
  3. package/dist/calculators/index.js +304 -0
  4. package/dist/calculators/index.js.map +1 -0
  5. package/dist/employee-identity-Cq2wo9-2.d.ts +490 -0
  6. package/dist/index-DjB72l6e.d.ts +3742 -0
  7. package/dist/index.d.ts +2924 -0
  8. package/dist/index.js +10648 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/prorating.calculator-C7sdFiG2.d.ts +135 -0
  11. package/dist/schemas/index.d.ts +4 -0
  12. package/dist/schemas/index.js +1452 -0
  13. package/dist/schemas/index.js.map +1 -0
  14. package/dist/types-BVDjiVGS.d.ts +1856 -0
  15. package/dist/utils/index.d.ts +995 -0
  16. package/dist/utils/index.js +1629 -0
  17. package/dist/utils/index.js.map +1 -0
  18. package/package.json +77 -24
  19. package/src/config.js +0 -177
  20. package/src/core/compensation.manager.js +0 -242
  21. package/src/core/employment.manager.js +0 -224
  22. package/src/core/payroll.manager.js +0 -499
  23. package/src/enums.js +0 -141
  24. package/src/factories/compensation.factory.js +0 -198
  25. package/src/factories/employee.factory.js +0 -173
  26. package/src/factories/payroll.factory.js +0 -247
  27. package/src/hrm.orchestrator.js +0 -139
  28. package/src/index.js +0 -172
  29. package/src/init.js +0 -41
  30. package/src/models/payroll-record.model.js +0 -126
  31. package/src/plugins/employee.plugin.js +0 -157
  32. package/src/schemas/employment.schema.js +0 -126
  33. package/src/services/compensation.service.js +0 -231
  34. package/src/services/employee.service.js +0 -162
  35. package/src/services/payroll.service.js +0 -213
  36. package/src/utils/calculation.utils.js +0 -91
  37. package/src/utils/date.utils.js +0 -120
  38. package/src/utils/logger.js +0 -36
  39. package/src/utils/query-builders.js +0 -185
  40. package/src/utils/validation.utils.js +0 -122
@@ -0,0 +1,2924 @@
1
+ import { E as EmployeeDocument, q as PayrollRecordDocument, r as AnyDocument, s as PayrollInstance, t as PayrollInitConfig, u as PayrollPluginDefinition, v as PayrollEventMap, w as WebhookConfig, x as PayrollEventType, y as WebhookDelivery, H as HireEmployeeParams, U as UpdateEmploymentParams, z as TerminateEmployeeParams, R as ReHireEmployeeParams, O as ObjectIdLike, d as OperationContext, F as EmployeeIdentityMode, G as UpdateSalaryParams, I as AddAllowanceParams, J as RemoveAllowanceParams, K as AddDeductionParams, M as RemoveDeductionParams, N as UpdateBankDetailsParams, Q as ProcessSalaryParams, S as ProcessSalaryResult, V as ProcessBulkPayrollParams, X as BulkPayrollResult, Y as PayrollHistoryParams, Z as PayrollSummaryParams, _ as PayrollSummaryResult, $ as ExportPayrollParams, a0 as VoidPayrollParams, a1 as VoidPayrollResult, a2 as ReversePayrollParams, a3 as ReversePayrollResult, a4 as RestorePayrollParams, a5 as RestorePayrollResult, a6 as GetPendingTaxParams, T as TaxWithholdingDocument, a7 as TaxSummaryParams, a8 as TaxSummaryResult, a9 as MarkTaxPaidParams, g as LeaveRequestDocument, aa as DeepPartial, ab as HRMConfig, ac as SingleTenantConfig, i as Logger, ad as PayrollBreakdown, ae as ObjectId, h as LeaveRequestStatus, f as TaxStatus, L as LeaveType, e as TaxType, p as PayrollStatus, o as Department, n as EmploymentType, af as OrgRole, c as LeaveInitConfig, ag as WorkSchedule, ah as PaymentFrequency, A as Allowance, D as Deduction, B as BankDetails, C as Compensation, ai as TerminationReason, aj as HttpError, ak as ErrorCode, al as AttendanceInput } from './types-BVDjiVGS.js';
2
+ export { am as AccrueLeaveOptions, an as AllowanceType, ao as AnyModel, ap as BulkPayrollProgress, j as CompensationBreakdownResult, aq as DataRetentionConfig, ar as DeductionType, as as EmployeeHiredEvent, at as EmployeeIdMode, au as EmployeeOperationParams, l as EmployeeStatus, m as EmployeeValidationResult, av as EmploymentConfig, aw as EmploymentHistoryEntry, ax as EventPayload, ay as EventPayloadBase, az as FilterQuery, aA as GetEmployeeParams, aB as HRMTransactionCategory, a as LeaveBalance, aC as LeaveHistoryFilters, b as LeaveSummaryResult, aD as Nullable, P as PayPeriodInfo, aE as PaymentMethod, aF as PayrollConfig, aG as PayrollCorrection, aH as PayrollEmployee, aI as PayrollEvent, aJ as PayrollPeriod, aK as PayrollPlugin, aL as PayrollStats, aM as PluginFunction, aN as PluginType, aO as QueryOptions, aP as RequestLeaveInput, aQ as ResetAnnualLeaveOptions, aR as ReviewLeaveRequestInput, aS as RoleMappingConfig, aT as SalaryBand, aU as SalaryBandRange, aV as SalaryConfig, aW as SalaryProcessedEvent, aX as TaxBracket, k as TaxCalculationResult, aY as TaxSummaryByType, aZ as UserReference, a_ as ValidationConfig, a$ as WebhookManager, b0 as WithPayroll, W as WorkingDaysOptions } from './types-BVDjiVGS.js';
3
+ import * as mongoose from 'mongoose';
4
+ import { ClientSession, Model, Schema, SchemaDefinition } from 'mongoose';
5
+ import { ITransaction, ITransactionCreateInput } from '@classytic/shared-types';
6
+ import { Plugin } from '@classytic/mongokit';
7
+ export { L as LeaveRequestModel, P as PayrollSchemaOptions, T as TaxWithholdingModel, a as allowanceSchema, b as applyEmployeeIndexes, c as applyLeaveRequestIndexes, d as applyPayrollRecordIndexes, e as applyTaxWithholdingIndexes, f as bankDetailsSchema, g as compensationSchema, h as createEmployeeSchema, i as createEmploymentFields, j as createPayrollRecordFields, k as createPayrollRecordSchema, l as deductionSchema, m as employmentHistorySchema, n as getLeaveRequestFields, o as getLeaveRequestModel, p as getTaxWithholdingFields, q as getTaxWithholdingModel, r as leaveBalanceFields, s as leaveBalanceSchema, t as leaveRequestIndexes, u as leaveRequestSchema, v as payrollStatsSchema, w as taxWithholdingIndexes, x as taxWithholdingSchema, y as workScheduleSchema } from './index-DjB72l6e.js';
8
+ export { P as ProRatingInput, b as ProRatingResult, a as applyProRating, c as calculateProRating, s as shouldProRate } from './prorating.calculator-C7sdFiG2.js';
9
+ export { C as ContainerLike, D as DEFAULT_CARRY_OVER, a as DEFAULT_LEAVE_ALLOCATIONS, b as EmployeeIdType, c as EmployeeQueryFilter, R as ResolveOrganizationIdParams, S as SecureEmployeeLookupOptions, d as accrueLeaveToBalance, e as calculateCarryOver, f as calculateLeaveDays, g as calculateUnpaidLeaveDeduction, h as detectEmployeeIdType, i as employeeExistsSecure, j as findEmployeeSecure, k as findEmployeesSecure, l as formatEmployeeId, m as getAvailableDays, n as getLeaveBalance, o as getLeaveBalances, p as getLeaveSummary, q as getUnpaidLeaveDays, r as hasLeaveBalance, s as initializeLeaveBalances, t as isObjectIdEmployeeId, u as isStringEmployeeId, v as normalizeEmployeeId, w as proRateAllocation, x as requireOrganizationId, y as resolveOrganizationId, z as tryResolveOrganizationId, A as validateOrganizationId } from './employee-identity-Cq2wo9-2.js';
10
+ export { AttendanceDeductionInput, AttendanceDeductionResult, ProcessedAllowance, ProcessedDeduction, SalaryCalculationInput, calculateAttendanceDeduction, calculateDailyRate, calculateHourlyRate, calculatePartialDayDeduction, calculateSalaryBreakdown, calculateTotalAttendanceDeduction } from './calculators/index.js';
11
+ import 'bson';
12
+
13
+ /**
14
+ * Fully generic Payroll class for best-in-class TypeScript DX.
15
+ *
16
+ * Type parameters flow through to all methods, providing complete type inference.
17
+ *
18
+ * @typeParam TEmployee - Your Employee document type (extends EmployeeDocument)
19
+ * @typeParam TPayrollRecord - Your PayrollRecord document type (extends PayrollRecordDocument)
20
+ * @typeParam TTransaction - Your Transaction document type
21
+ * @typeParam TAttendance - Your Attendance document type (optional)
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // Full type inference
26
+ * const payroll = createPayrollInstance()
27
+ * .withModels({
28
+ * EmployeeModel, // Model<MyEmployeeDoc>
29
+ * PayrollRecordModel, // Model<MyPayrollDoc>
30
+ * TransactionModel, // Model<MyTransactionDoc>
31
+ * })
32
+ * .build();
33
+ *
34
+ * // employee is typed as MyEmployeeDoc
35
+ * const employee = await payroll.hire({ ... });
36
+ * ```
37
+ */
38
+ declare class Payroll<TEmployee extends EmployeeDocument = EmployeeDocument, TPayrollRecord extends PayrollRecordDocument = PayrollRecordDocument, TTransaction extends AnyDocument = AnyDocument, TAttendance extends AnyDocument = AnyDocument> implements PayrollInstance<TEmployee, TPayrollRecord, TTransaction, TAttendance> {
39
+ [key: string]: unknown;
40
+ private _container;
41
+ private _events;
42
+ private _plugins;
43
+ private _initialized;
44
+ private repositoryManager;
45
+ private salaryProcessingManager;
46
+ private bulkOperationsManager;
47
+ private employeeOperationsManager;
48
+ private compensationManager;
49
+ private payrollHistoryManager;
50
+ private payrollStateManager;
51
+ private _idempotency;
52
+ private _webhooks;
53
+ /**
54
+ * Create a new Payroll instance with its own container.
55
+ * Each instance is isolated - no shared global state.
56
+ */
57
+ constructor();
58
+ /**
59
+ * Initialize Payroll with models and configuration
60
+ */
61
+ initialize(config: PayrollInitConfig<TEmployee, TPayrollRecord, TTransaction, TAttendance>): this;
62
+ /**
63
+ * Check if initialized
64
+ */
65
+ isInitialized(): boolean;
66
+ /**
67
+ * Ensure initialized
68
+ */
69
+ private ensureInitialized;
70
+ /**
71
+ * Resolve employeeId to ObjectId _id (respects explicit mode)
72
+ *
73
+ * Mode priority:
74
+ * - 'objectId': Always treat as MongoDB ObjectId (direct _id lookup)
75
+ * - 'businessId': Always treat as business ID (lookup by employeeId field)
76
+ * - 'auto': Smart detection (ObjectId-like → _id, otherwise → businessId)
77
+ */
78
+ private resolveEmployeeId;
79
+ /**
80
+ * Create request-scoped services with proper organizationId filtering.
81
+ *
82
+ * SECURITY: Services are created from request-scoped repositories to ensure
83
+ * multi-tenant isolation at the query level.
84
+ *
85
+ * @param repos - Request-scoped repositories
86
+ */
87
+ private getServicesForRequest;
88
+ /**
89
+ * Get models (strongly typed)
90
+ */
91
+ private get models();
92
+ /**
93
+ * Create request-scoped repositories with proper organizationId filtering.
94
+ *
95
+ * SECURITY: This ensures multi-tenant isolation at the query level by creating
96
+ * repositories with the request-specific organizationId injected into plugins.
97
+ *
98
+ * @param organizationId - Required in multi-tenant mode, optional in single-tenant
99
+ */
100
+ private getReposForRequest;
101
+ /**
102
+ * Resolve organizationId for the current operation.
103
+ *
104
+ * SECURITY:
105
+ * - Multi-tenant mode: organizationId MUST be provided in params
106
+ * - Single-tenant with autoInject=true (default): Uses container organizationId
107
+ * - Single-tenant with autoInject=false: organizationId MUST be provided in params
108
+ *
109
+ * @param providedOrgId - OrganizationId from operation parameters
110
+ * @returns Resolved ObjectId
111
+ * @throws SecurityError if organizationId is missing when required
112
+ */
113
+ private resolveOrganizationId;
114
+ /**
115
+ * Get config
116
+ */
117
+ private get config();
118
+ /**
119
+ * Get container (for org resolution and single-tenant detection)
120
+ */
121
+ private get container();
122
+ /**
123
+ * Find employee securely with organizational isolation at query level.
124
+ *
125
+ * SECURITY: Creates request-scoped repositories with organizationId injected into
126
+ * query filters, ensuring multi-tenant isolation at the database level.
127
+ *
128
+ * In multi-tenant mode, organizationId MUST be provided in options.
129
+ * In single-tenant mode, organizationId is retrieved from container.
130
+ */
131
+ private findEmployee;
132
+ /**
133
+ * Register a plugin
134
+ */
135
+ use(plugin: PayrollPluginDefinition): Promise<this>;
136
+ /**
137
+ * Subscribe to events
138
+ */
139
+ on<K extends keyof PayrollEventMap>(event: K, handler: (payload: PayrollEventMap[K]) => void | Promise<void>): () => void;
140
+ /**
141
+ * Register webhook URL for events (Stripe-style)
142
+ */
143
+ registerWebhook(config: WebhookConfig): void;
144
+ /**
145
+ * Unregister webhook URL
146
+ */
147
+ unregisterWebhook(url: string): void;
148
+ /**
149
+ * Get webhook delivery log
150
+ */
151
+ getWebhookDeliveries(options?: {
152
+ event?: PayrollEventType;
153
+ status?: 'pending' | 'sent' | 'failed';
154
+ limit?: number;
155
+ }): WebhookDelivery[];
156
+ /**
157
+ * Setup webhook bridge (connects event bus to webhook manager)
158
+ */
159
+ private setupWebhookBridge;
160
+ /**
161
+ * Hire a new employee
162
+ */
163
+ hire(params: HireEmployeeParams): Promise<TEmployee>;
164
+ /**
165
+ * Update employment details
166
+ * NOTE: Status changes to 'terminated' must use terminate() method
167
+ */
168
+ updateEmployment(params: UpdateEmploymentParams): Promise<TEmployee>;
169
+ /**
170
+ * Terminate employee
171
+ */
172
+ terminate(params: TerminateEmployeeParams): Promise<TEmployee>;
173
+ /**
174
+ * Re-hire terminated employee
175
+ */
176
+ reHire(params: ReHireEmployeeParams): Promise<TEmployee>;
177
+ /**
178
+ * Get employee by ID
179
+ */
180
+ getEmployee(params: {
181
+ employeeId: ObjectIdLike | string;
182
+ employeeIdMode?: 'auto' | 'objectId' | 'businessId';
183
+ organizationId?: ObjectIdLike;
184
+ populateUser?: boolean;
185
+ session?: ClientSession;
186
+ context?: OperationContext;
187
+ }): Promise<TEmployee>;
188
+ /**
189
+ * Get employee by flexible identity (userId, employeeId, or email)
190
+ *
191
+ * Supports multiple identity modes with automatic fallback:
192
+ * - 'userId': Lookup by user account ID (traditional)
193
+ * - 'employeeId': Lookup by human-readable employee ID (e.g., "EMP-001")
194
+ * - 'email': Lookup by email address (for guest employees)
195
+ * - 'any': Try all modes until found
196
+ *
197
+ * @example
198
+ * // By user ID (traditional)
199
+ * const emp = await payroll.getEmployeeByIdentity({
200
+ * identity: userId,
201
+ * organizationId,
202
+ * mode: 'userId'
203
+ * });
204
+ *
205
+ * // By employee ID (human-readable)
206
+ * const emp = await payroll.getEmployeeByIdentity({
207
+ * identity: 'EMP-001',
208
+ * organizationId,
209
+ * mode: 'employeeId'
210
+ * });
211
+ *
212
+ * // By email (guest employees)
213
+ * const emp = await payroll.getEmployeeByIdentity({
214
+ * identity: 'driver@example.com',
215
+ * organizationId,
216
+ * mode: 'email'
217
+ * });
218
+ *
219
+ * // Auto-detect (uses config.identityMode + fallbacks)
220
+ * const emp = await payroll.getEmployeeByIdentity({
221
+ * identity: 'EMP-001',
222
+ * organizationId
223
+ * });
224
+ */
225
+ getEmployeeByIdentity(params: {
226
+ identity: ObjectIdLike | string;
227
+ organizationId?: ObjectIdLike;
228
+ mode?: EmployeeIdentityMode;
229
+ populateUser?: boolean;
230
+ session?: ClientSession;
231
+ }): Promise<TEmployee>;
232
+ /**
233
+ * Update employee salary
234
+ */
235
+ updateSalary(params: UpdateSalaryParams): Promise<TEmployee>;
236
+ /**
237
+ * Add allowance to employee
238
+ */
239
+ addAllowance(params: AddAllowanceParams): Promise<TEmployee>;
240
+ /**
241
+ * Remove allowance from employee
242
+ */
243
+ removeAllowance(params: RemoveAllowanceParams): Promise<TEmployee>;
244
+ /**
245
+ * Add deduction to employee
246
+ */
247
+ addDeduction(params: AddDeductionParams): Promise<TEmployee>;
248
+ /**
249
+ * Remove deduction from employee
250
+ */
251
+ removeDeduction(params: RemoveDeductionParams): Promise<TEmployee>;
252
+ /**
253
+ * Update bank details
254
+ */
255
+ updateBankDetails(params: UpdateBankDetailsParams): Promise<TEmployee>;
256
+ /**
257
+ * Process salary for single employee
258
+ *
259
+ * ATOMICITY GUARANTEE:
260
+ * This method ALWAYS ensures atomic operations. All database writes
261
+ * (PayrollRecord, Transaction, Employee stats) either all succeed or all fail.
262
+ *
263
+ * Transaction Handling:
264
+ * - No session provided: Creates session and starts transaction
265
+ * - Session provided WITHOUT transaction: Starts transaction on that session
266
+ * - Session provided WITH transaction: Uses existing transaction
267
+ *
268
+ * This means atomicity is enforced automatically - callers cannot
269
+ * accidentally cause partial writes by providing session without transaction.
270
+ *
271
+ * @example
272
+ * // Simple usage - transaction handled automatically
273
+ * await payroll.processSalary({ employeeId, organizationId, month, year });
274
+ *
275
+ * @example
276
+ * // Use existing session (transaction started automatically if needed)
277
+ * const session = await mongoose.startSession();
278
+ * await payroll.processSalary({
279
+ * employeeId,
280
+ * organizationId,
281
+ * month,
282
+ * year,
283
+ * context: { session }
284
+ * });
285
+ *
286
+ * @example
287
+ * // Nested in caller's transaction (uses existing transaction)
288
+ * await session.withTransaction(async () => {
289
+ * await payroll.processSalary({
290
+ * employeeId,
291
+ * organizationId,
292
+ * month,
293
+ * year,
294
+ * context: { session }
295
+ * });
296
+ * // Other operations...
297
+ * });
298
+ */
299
+ processSalary(params: ProcessSalaryParams): Promise<ProcessSalaryResult<TEmployee, TPayrollRecord, TTransaction>>;
300
+ /**
301
+ * Process bulk payroll for multiple employees
302
+ *
303
+ * ATOMICITY STRATEGY: Each employee is processed in its own transaction.
304
+ * This allows partial success - some employees can succeed while others fail.
305
+ * Failed employees don't affect successful ones.
306
+ *
307
+ * NEW FEATURES (all optional, backward compatible):
308
+ * - Progress tracking via onProgress callback
309
+ * - Cancellation support via AbortSignal
310
+ * - Batch processing to prevent resource exhaustion
311
+ * - Concurrency control for parallel processing
312
+ *
313
+ * @example Basic usage (unchanged)
314
+ * ```typescript
315
+ * const result = await payroll.processBulkPayroll({
316
+ * organizationId, month, year
317
+ * });
318
+ * ```
319
+ *
320
+ * @example With progress tracking
321
+ * ```typescript
322
+ * await payroll.processBulkPayroll({
323
+ * organizationId, month, year,
324
+ * onProgress: (p) => console.log(`${p.percentage}% done`)
325
+ * });
326
+ * ```
327
+ *
328
+ * @example With job queue integration
329
+ * ```typescript
330
+ * await payroll.processBulkPayroll({
331
+ * organizationId, month, year,
332
+ * batchSize: 10,
333
+ * onProgress: async (p) => {
334
+ * await Job.findByIdAndUpdate(jobId, { progress: p });
335
+ * }
336
+ * });
337
+ * ```
338
+ *
339
+ * @example With cancellation
340
+ * ```typescript
341
+ * const controller = new AbortController();
342
+ * payroll.processBulkPayroll({ signal: controller.signal });
343
+ * // Later: controller.abort();
344
+ * ```
345
+ */
346
+ processBulkPayroll(params: ProcessBulkPayrollParams): Promise<BulkPayrollResult>;
347
+ /**
348
+ * Get payroll history
349
+ */
350
+ payrollHistory(params: PayrollHistoryParams): Promise<TPayrollRecord[]>;
351
+ /**
352
+ * Get payroll summary
353
+ */
354
+ payrollSummary(params: PayrollSummaryParams): Promise<PayrollSummaryResult>;
355
+ /**
356
+ * Export payroll data
357
+ */
358
+ exportPayroll(params: ExportPayrollParams): Promise<TPayrollRecord[]>;
359
+ /**
360
+ * Void a payroll record (before payment)
361
+ *
362
+ * Use for payrolls that haven't been paid yet (pending, processing, failed).
363
+ * Creates audit trail but doesn't create a reversal transaction.
364
+ *
365
+ * @example
366
+ * ```typescript
367
+ * await payroll.voidPayroll({
368
+ * organizationId: org._id,
369
+ * payrollRecordId: record._id,
370
+ * reason: 'Test payroll - not intended for production',
371
+ * context: { userId: admin._id },
372
+ * });
373
+ * ```
374
+ */
375
+ voidPayroll(params: VoidPayrollParams): Promise<VoidPayrollResult>;
376
+ /**
377
+ * Reverse a paid payroll
378
+ *
379
+ * Creates a reversal (negative) transaction to offset the original payment.
380
+ * Required for compliance as it maintains a full audit trail.
381
+ *
382
+ * @example
383
+ * ```typescript
384
+ * const result = await payroll.reversePayroll({
385
+ * organizationId: org._id,
386
+ * payrollRecordId: record._id,
387
+ * reason: 'Duplicate payment - reversing',
388
+ * createReversalTransaction: true,
389
+ * });
390
+ * ```
391
+ */
392
+ reversePayroll(params: ReversePayrollParams): Promise<ReversePayrollResult>;
393
+ /**
394
+ * Restore a voided payroll
395
+ *
396
+ * Only works for voided payrolls (not reversed ones, as they have financial transactions).
397
+ *
398
+ * @example
399
+ * ```typescript
400
+ * await payroll.restorePayroll({
401
+ * organizationId: org._id,
402
+ * payrollRecordId: record._id,
403
+ * reason: 'Voided in error, restoring',
404
+ * });
405
+ * ```
406
+ */
407
+ restorePayroll(params: RestorePayrollParams): Promise<RestorePayrollResult>;
408
+ /**
409
+ * Get pending tax withholdings with optional filters
410
+ */
411
+ getPendingTaxWithholdings(params: GetPendingTaxParams): Promise<TaxWithholdingDocument[]>;
412
+ /**
413
+ * Get tax summary aggregated by type, period, or employee
414
+ */
415
+ getTaxSummary(params: TaxSummaryParams): Promise<TaxSummaryResult>;
416
+ /**
417
+ * Mark tax withholdings as paid
418
+ *
419
+ * Updates status, optionally creates government payment transaction,
420
+ * and emits tax:paid event
421
+ */
422
+ markTaxWithholdingsPaid(params: MarkTaxPaidParams): Promise<{
423
+ withholdings: TaxWithholdingDocument[];
424
+ transaction?: any;
425
+ }>;
426
+ /**
427
+ * Calculate salary breakdown
428
+ *
429
+ * Delegates to pure calculator for testability and reusability
430
+ */
431
+ private calculateSalaryBreakdown;
432
+ /**
433
+ * Calculate attendance deduction using working days (not calendar days)
434
+ */
435
+ private calculateAttendanceDeduction;
436
+ private updatePayrollStats;
437
+ /**
438
+ * Create a new Payroll instance with default types
439
+ */
440
+ static create<E extends EmployeeDocument = EmployeeDocument, P extends PayrollRecordDocument = PayrollRecordDocument, T extends AnyDocument = AnyDocument, A extends AnyDocument = AnyDocument>(): Payroll<E, P, T, A>;
441
+ }
442
+ /**
443
+ * Generic models configuration - infers types from your models
444
+ */
445
+ interface ModelsConfig<TEmployee extends EmployeeDocument = EmployeeDocument, TPayrollRecord extends PayrollRecordDocument = PayrollRecordDocument, TTransaction extends AnyDocument = AnyDocument, TAttendance extends AnyDocument = AnyDocument, TLeaveRequest extends LeaveRequestDocument = LeaveRequestDocument, TTaxWithholding extends TaxWithholdingDocument = TaxWithholdingDocument> {
446
+ EmployeeModel: Model<TEmployee>;
447
+ PayrollRecordModel: Model<TPayrollRecord>;
448
+ TransactionModel: Model<TTransaction>;
449
+ AttendanceModel?: Model<TAttendance> | null;
450
+ LeaveRequestModel?: Model<TLeaveRequest> | null;
451
+ TaxWithholdingModel?: Model<TTaxWithholding> | null;
452
+ }
453
+ /**
454
+ * Generic Payroll Builder with full type inference.
455
+ *
456
+ * Types flow from withModels() through to build(), giving you a fully typed Payroll instance.
457
+ *
458
+ * @typeParam TEmployee - Inferred from EmployeeModel
459
+ * @typeParam TPayrollRecord - Inferred from PayrollRecordModel
460
+ * @typeParam TTransaction - Inferred from TransactionModel
461
+ * @typeParam TAttendance - Inferred from AttendanceModel
462
+ *
463
+ * @example
464
+ * ```typescript
465
+ * // Types are automatically inferred!
466
+ * const payroll = createPayrollInstance()
467
+ * .withModels({
468
+ * EmployeeModel, // Model<MyEmployee>
469
+ * PayrollRecordModel, // Model<MyPayroll>
470
+ * TransactionModel, // Model<MyTransaction>
471
+ * })
472
+ * .build(); // Returns PayrollInstance<MyEmployee, MyPayroll, MyTransaction, AnyDocument>
473
+ * ```
474
+ */
475
+ declare class PayrollBuilder<TEmployee extends EmployeeDocument = EmployeeDocument, TPayrollRecord extends PayrollRecordDocument = PayrollRecordDocument, TTransaction extends AnyDocument = AnyDocument, TAttendance extends AnyDocument = AnyDocument, TLeaveRequest extends LeaveRequestDocument = LeaveRequestDocument, TTaxWithholding extends TaxWithholdingDocument = TaxWithholdingDocument> {
476
+ private _models;
477
+ private _config;
478
+ private _singleTenant;
479
+ private _logger;
480
+ /**
481
+ * Set models - types are inferred automatically
482
+ *
483
+ * @example
484
+ * ```typescript
485
+ * .withModels({
486
+ * EmployeeModel, // Your typed model
487
+ * PayrollRecordModel,
488
+ * TransactionModel,
489
+ * AttendanceModel, // Optional
490
+ * })
491
+ * ```
492
+ */
493
+ withModels<E extends EmployeeDocument, P extends PayrollRecordDocument, T extends AnyDocument, A extends AnyDocument = AnyDocument, L extends LeaveRequestDocument = LeaveRequestDocument, TW extends TaxWithholdingDocument = TaxWithholdingDocument>(models: ModelsConfig<E, P, T, A, L, TW>): PayrollBuilder<E, P, T, A, L, TW>;
494
+ /**
495
+ * Set config overrides
496
+ */
497
+ withConfig(config: DeepPartial<HRMConfig>): this;
498
+ /**
499
+ * Enable single-tenant mode
500
+ *
501
+ * Use this when building a single-organization HRM (no organizationId needed)
502
+ *
503
+ * @example
504
+ * ```typescript
505
+ * const payroll = createPayrollInstance()
506
+ * .withModels({ EmployeeModel, PayrollRecordModel, TransactionModel })
507
+ * .withSingleTenant({ organizationId: 'my-company' })
508
+ * .build();
509
+ * ```
510
+ */
511
+ withSingleTenant(config: SingleTenantConfig): this;
512
+ /**
513
+ * Enable single-tenant mode (shorthand)
514
+ *
515
+ * Alias for withSingleTenant() - consistent with @classytic/clockin API
516
+ *
517
+ * @example
518
+ * ```typescript
519
+ * const payroll = createPayrollInstance()
520
+ * .withModels({ ... })
521
+ * .forSingleTenant() // ← No organizationId needed!
522
+ * .build();
523
+ * ```
524
+ */
525
+ forSingleTenant(config?: SingleTenantConfig): this;
526
+ /**
527
+ * Set custom logger
528
+ */
529
+ withLogger(logger: Logger): this;
530
+ /**
531
+ * Build and initialize Payroll instance with inferred types
532
+ */
533
+ build(): PayrollInstance<TEmployee, TPayrollRecord, TTransaction, TAttendance>;
534
+ }
535
+ /**
536
+ * Create a new Payroll builder
537
+ */
538
+ declare function createPayrollInstance(): PayrollBuilder;
539
+
540
+ /**
541
+ * Transaction Interface
542
+ * @classytic/payroll
543
+ *
544
+ * Payroll uses the unified transaction interface from @classytic/shared-types
545
+ * so revenue and payroll share a single cashflow event model.
546
+ */
547
+
548
+ /**
549
+ * Core transaction interface expected by payroll package
550
+ * Apps must provide a Transaction model with AT LEAST these fields
551
+ */
552
+ type IPayrollTransaction = ITransaction;
553
+ /**
554
+ * Transaction write input (what payroll package creates)
555
+ */
556
+ type IPayrollTransactionCreateInput = ITransactionCreateInput;
557
+ /**
558
+ * Type guard to check if object is a Transaction
559
+ */
560
+ declare function isPayrollTransaction(obj: unknown): obj is IPayrollTransaction;
561
+
562
+ /**
563
+ * @classytic/payroll - Transaction Factory
564
+ *
565
+ * Pure functions for building transaction objects aligned with @classytic/shared-types.
566
+ * Ensures consistency with revenue package for unified cashflow.
567
+ *
568
+ * @packageDocumentation
569
+ */
570
+
571
+ /**
572
+ * Input for creating a payroll transaction
573
+ */
574
+ interface CreatePayrollTransactionInput {
575
+ organizationId: ObjectIdLike;
576
+ employee: {
577
+ _id: ObjectIdLike;
578
+ userId?: ObjectIdLike | {
579
+ _id: ObjectIdLike;
580
+ name?: string;
581
+ } | null;
582
+ employeeId: string;
583
+ email?: string;
584
+ compensation: {
585
+ currency?: string;
586
+ };
587
+ };
588
+ payrollRecord: {
589
+ _id: ObjectIdLike;
590
+ };
591
+ breakdown: PayrollBreakdown;
592
+ period: {
593
+ month: number;
594
+ year: number;
595
+ };
596
+ paymentDate: Date;
597
+ paymentMethod?: string;
598
+ processedBy?: ObjectIdLike;
599
+ idempotencyKey?: string;
600
+ jurisdiction?: string;
601
+ defaultCurrency?: string;
602
+ }
603
+ /**
604
+ * Input for creating a tax payment transaction
605
+ */
606
+ interface CreateTaxPaymentTransactionInput {
607
+ organizationId: ObjectIdLike;
608
+ totalAmount: number;
609
+ currency: string;
610
+ referenceNumber?: string;
611
+ notes?: string;
612
+ withholdingIds: ObjectIdLike[];
613
+ }
614
+ /**
615
+ * Create payroll transaction aligned with @classytic/shared-types
616
+ *
617
+ * This is the SINGLE SOURCE OF TRUTH for payroll transaction structure.
618
+ * Aligns with revenue package for unified cashflow.
619
+ *
620
+ * @param input - Payroll transaction parameters
621
+ * @returns Transaction data ready for DB creation (ITransactionCreateInput)
622
+ *
623
+ * @pure This function has no side effects
624
+ */
625
+ declare function createPayrollTransaction(input: CreatePayrollTransactionInput): ITransactionCreateInput;
626
+ /**
627
+ * Create tax payment transaction aligned with @classytic/shared-types
628
+ *
629
+ * For government tax payments (withholding remittance).
630
+ *
631
+ * @param input - Tax payment parameters
632
+ * @returns Transaction data ready for DB creation (ITransactionCreateInput)
633
+ *
634
+ * @pure This function has no side effects
635
+ */
636
+ declare function createTaxPaymentTransaction(input: CreateTaxPaymentTransactionInput): ITransactionCreateInput;
637
+ /**
638
+ * Transaction Factory class (for builder pattern if needed)
639
+ */
640
+ declare class TransactionFactory {
641
+ static createPayrollTransaction: typeof createPayrollTransaction;
642
+ static createTaxPaymentTransaction: typeof createTaxPaymentTransaction;
643
+ }
644
+
645
+ /**
646
+ * Idempotency Manager
647
+ *
648
+ * Ensures operations are not duplicated when called with the same key.
649
+ * Uses Stripe-style idempotency pattern for payroll operations.
650
+ *
651
+ * ## Important: In-Memory Cache Limitations
652
+ *
653
+ * This implementation uses an **in-memory LRU cache** which has the following limitations:
654
+ *
655
+ * - **Does NOT persist across server restarts** - cache is lost on restart
656
+ * - **Does NOT work across multiple server instances** - each instance has its own cache
657
+ * - **Only prevents duplicates within the same process lifetime**
658
+ *
659
+ * For production deployments with horizontal scaling or high availability requirements,
660
+ * you should implement database-backed idempotency. See the Payroll class documentation
661
+ * for implementation examples.
662
+ *
663
+ * The database's unique index on `{ employeeId, period.month, period.year }` serves as
664
+ * the primary duplicate protection - this cache is a secondary optimization layer.
665
+ *
666
+ * @see https://stripe.com/docs/api/idempotent_requests
667
+ */
668
+
669
+ interface IdempotentResult<T = any> {
670
+ value: T;
671
+ cached: boolean;
672
+ createdAt: Date;
673
+ }
674
+ /**
675
+ * In-memory idempotency manager for preventing duplicate operations.
676
+ *
677
+ * @warning This is an in-memory cache. For production horizontal scaling,
678
+ * implement database-backed idempotency instead.
679
+ */
680
+ declare class IdempotencyManager {
681
+ private cache;
682
+ private static hasLoggedWarning;
683
+ constructor(options?: {
684
+ max?: number;
685
+ ttl?: number;
686
+ suppressWarning?: boolean;
687
+ });
688
+ /**
689
+ * Check if key exists and return cached result
690
+ */
691
+ get<T>(key: string): IdempotentResult<T> | null;
692
+ /**
693
+ * Store result for idempotency key
694
+ */
695
+ set<T>(key: string, value: T): void;
696
+ /**
697
+ * Execute function with idempotency protection
698
+ */
699
+ execute<T>(key: string, fn: () => Promise<T>): Promise<IdempotentResult<T>>;
700
+ /**
701
+ * Clear a specific key
702
+ */
703
+ delete(key: string): void;
704
+ /**
705
+ * Clear all keys
706
+ */
707
+ clear(): void;
708
+ /**
709
+ * Get cache stats
710
+ */
711
+ stats(): {
712
+ size: number;
713
+ max: number;
714
+ };
715
+ }
716
+ /**
717
+ * Generate idempotency key for payroll operations
718
+ */
719
+ declare function generatePayrollIdempotencyKey(organizationId: ObjectIdLike, employeeId: ObjectIdLike, month: number, year: number): string;
720
+
721
+ /**
722
+ * Repository plugins for mongokit integration
723
+ */
724
+
725
+ /**
726
+ * Multi-tenant plugin - automatically injects organizationId into queries
727
+ */
728
+ declare function multiTenantPlugin(organizationId?: ObjectId): Plugin;
729
+
730
+ /**
731
+ * @classytic/payroll - Timeline Audit Integration
732
+ *
733
+ * Integration with @classytic/mongoose-timeline-audit for comprehensive audit trails.
734
+ * Provides automatic tracking of WHO performed WHAT action and WHEN.
735
+ *
736
+ * ## Setup
737
+ *
738
+ * 1. Install mongoose-timeline-audit:
739
+ * ```bash
740
+ * npm install @classytic/mongoose-timeline-audit
741
+ * ```
742
+ *
743
+ * 2. Apply to your schemas BEFORE registering with Mongoose:
744
+ * ```typescript
745
+ * import timelineAuditPlugin from '@classytic/mongoose-timeline-audit';
746
+ * import { PAYROLL_EVENTS } from '@classytic/payroll';
747
+ *
748
+ * // Apply to Employee schema
749
+ * employeeSchema.plugin(timelineAuditPlugin, {
750
+ * ownerField: 'organizationId',
751
+ * eventLimits: PAYROLL_EVENTS.EMPLOYEE.limits,
752
+ * });
753
+ *
754
+ * // Apply to PayrollRecord schema
755
+ * payrollRecordSchema.plugin(timelineAuditPlugin, {
756
+ * ownerField: 'organizationId',
757
+ * eventLimits: PAYROLL_EVENTS.PAYROLL.limits,
758
+ * });
759
+ * ```
760
+ *
761
+ * 3. Use the Payroll events to add timeline entries:
762
+ * ```typescript
763
+ * payroll.on('employee:hired', async ({ data }) => {
764
+ * const employee = await Employee.findById(data.employee.id);
765
+ * employee.addTimelineEvent(
766
+ * PAYROLL_EVENTS.EMPLOYEE.HIRED,
767
+ * `Hired as ${data.employee.position}`,
768
+ * request, // Express request for actor tracking
769
+ * { department: data.employee.department }
770
+ * );
771
+ * await employee.save();
772
+ * });
773
+ * ```
774
+ *
775
+ * @module @classytic/payroll/timeline-audit
776
+ */
777
+ /**
778
+ * Standard payroll events for timeline tracking
779
+ *
780
+ * Use these constants with mongoose-timeline-audit's addTimelineEvent()
781
+ * to maintain consistent event naming across your application.
782
+ */
783
+ declare const PAYROLL_EVENTS: {
784
+ /**
785
+ * Employee lifecycle events
786
+ */
787
+ readonly EMPLOYEE: {
788
+ /** Employee was hired */
789
+ readonly HIRED: "employee.hired";
790
+ /** Employee was terminated */
791
+ readonly TERMINATED: "employee.terminated";
792
+ /** Employee was re-hired after termination */
793
+ readonly REHIRED: "employee.rehired";
794
+ /** Employee status changed (active, on_leave, suspended) */
795
+ readonly STATUS_CHANGED: "employee.status_changed";
796
+ /** Employee department/position changed */
797
+ readonly ROLE_CHANGED: "employee.role_changed";
798
+ /** Employee probation ended */
799
+ readonly PROBATION_ENDED: "employee.probation_ended";
800
+ /** Recommended event limits for employee timeline */
801
+ readonly limits: {
802
+ readonly 'employee.status_changed': 50;
803
+ readonly 'employee.role_changed': 20;
804
+ };
805
+ };
806
+ /**
807
+ * Compensation events
808
+ */
809
+ readonly COMPENSATION: {
810
+ /** Base salary was updated */
811
+ readonly SALARY_UPDATED: "compensation.salary_updated";
812
+ /** Allowance was added */
813
+ readonly ALLOWANCE_ADDED: "compensation.allowance_added";
814
+ /** Allowance was removed */
815
+ readonly ALLOWANCE_REMOVED: "compensation.allowance_removed";
816
+ /** Deduction was added */
817
+ readonly DEDUCTION_ADDED: "compensation.deduction_added";
818
+ /** Deduction was removed */
819
+ readonly DEDUCTION_REMOVED: "compensation.deduction_removed";
820
+ /** Bank details were updated */
821
+ readonly BANK_UPDATED: "compensation.bank_updated";
822
+ /** Recommended event limits */
823
+ readonly limits: {
824
+ readonly 'compensation.salary_updated': 24;
825
+ readonly 'compensation.allowance_added': 20;
826
+ readonly 'compensation.allowance_removed': 20;
827
+ readonly 'compensation.deduction_added': 20;
828
+ readonly 'compensation.deduction_removed': 20;
829
+ readonly 'compensation.bank_updated': 10;
830
+ };
831
+ };
832
+ /**
833
+ * Payroll processing events
834
+ */
835
+ readonly PAYROLL: {
836
+ /** Salary was processed */
837
+ readonly PROCESSED: "payroll.processed";
838
+ /** Payroll was voided (before payment) */
839
+ readonly VOIDED: "payroll.voided";
840
+ /** Payroll was reversed (after payment) */
841
+ readonly REVERSED: "payroll.reversed";
842
+ /** Payroll was restored from voided state */
843
+ readonly RESTORED: "payroll.restored";
844
+ /** Payroll export was generated */
845
+ readonly EXPORTED: "payroll.exported";
846
+ /** Recommended event limits */
847
+ readonly limits: {
848
+ readonly 'payroll.processed': 36;
849
+ readonly 'payroll.voided': 10;
850
+ readonly 'payroll.reversed': 10;
851
+ readonly 'payroll.restored': 5;
852
+ readonly 'payroll.exported': 20;
853
+ };
854
+ };
855
+ /**
856
+ * Tax withholding events
857
+ */
858
+ readonly TAX: {
859
+ /** Tax was withheld */
860
+ readonly WITHHELD: "tax.withheld";
861
+ /** Tax was submitted to authorities */
862
+ readonly SUBMITTED: "tax.submitted";
863
+ /** Tax payment was made */
864
+ readonly PAID: "tax.paid";
865
+ /** Tax withholding was cancelled */
866
+ readonly CANCELLED: "tax.cancelled";
867
+ /** Recommended event limits */
868
+ readonly limits: {
869
+ readonly 'tax.withheld': 36;
870
+ readonly 'tax.submitted': 12;
871
+ readonly 'tax.paid': 12;
872
+ readonly 'tax.cancelled': 10;
873
+ };
874
+ };
875
+ /**
876
+ * Leave management events
877
+ */
878
+ readonly LEAVE: {
879
+ /** Leave was requested */
880
+ readonly REQUESTED: "leave.requested";
881
+ /** Leave was approved */
882
+ readonly APPROVED: "leave.approved";
883
+ /** Leave was rejected */
884
+ readonly REJECTED: "leave.rejected";
885
+ /** Leave was cancelled */
886
+ readonly CANCELLED: "leave.cancelled";
887
+ /** Leave balance was accrued */
888
+ readonly ACCRUED: "leave.accrued";
889
+ /** Annual leave was reset */
890
+ readonly RESET: "leave.reset";
891
+ /** Recommended event limits */
892
+ readonly limits: {
893
+ readonly 'leave.requested': 50;
894
+ readonly 'leave.approved': 50;
895
+ readonly 'leave.rejected': 20;
896
+ readonly 'leave.cancelled': 20;
897
+ readonly 'leave.accrued': 12;
898
+ readonly 'leave.reset': 5;
899
+ };
900
+ };
901
+ };
902
+ /**
903
+ * All payroll event types (for TypeScript)
904
+ */
905
+ type PayrollTimelineEvent = typeof PAYROLL_EVENTS.EMPLOYEE[keyof typeof PAYROLL_EVENTS.EMPLOYEE] | typeof PAYROLL_EVENTS.COMPENSATION[keyof typeof PAYROLL_EVENTS.COMPENSATION] | typeof PAYROLL_EVENTS.PAYROLL[keyof typeof PAYROLL_EVENTS.PAYROLL] | typeof PAYROLL_EVENTS.TAX[keyof typeof PAYROLL_EVENTS.TAX] | typeof PAYROLL_EVENTS.LEAVE[keyof typeof PAYROLL_EVENTS.LEAVE];
906
+ /**
907
+ * Recommended timeline audit configuration for Employee model
908
+ */
909
+ declare const EMPLOYEE_TIMELINE_CONFIG: {
910
+ ownerField: string;
911
+ fieldName: string;
912
+ hideByDefault: boolean;
913
+ eventLimits: {
914
+ 'compensation.salary_updated': 24;
915
+ 'compensation.allowance_added': 20;
916
+ 'compensation.allowance_removed': 20;
917
+ 'compensation.deduction_added': 20;
918
+ 'compensation.deduction_removed': 20;
919
+ 'compensation.bank_updated': 10;
920
+ 'employee.status_changed': 50;
921
+ 'employee.role_changed': 20;
922
+ };
923
+ };
924
+ /**
925
+ * Recommended timeline audit configuration for PayrollRecord model
926
+ */
927
+ declare const PAYROLL_RECORD_TIMELINE_CONFIG: {
928
+ ownerField: string;
929
+ fieldName: string;
930
+ hideByDefault: boolean;
931
+ eventLimits: {
932
+ readonly 'payroll.processed': 36;
933
+ readonly 'payroll.voided': 10;
934
+ readonly 'payroll.reversed': 10;
935
+ readonly 'payroll.restored': 5;
936
+ readonly 'payroll.exported': 20;
937
+ };
938
+ };
939
+ /**
940
+ * Recommended timeline audit configuration for LeaveRequest model
941
+ */
942
+ declare const LEAVE_REQUEST_TIMELINE_CONFIG: {
943
+ ownerField: string;
944
+ fieldName: string;
945
+ hideByDefault: boolean;
946
+ eventLimits: {
947
+ readonly 'leave.requested': 50;
948
+ readonly 'leave.approved': 50;
949
+ readonly 'leave.rejected': 20;
950
+ readonly 'leave.cancelled': 20;
951
+ readonly 'leave.accrued': 12;
952
+ readonly 'leave.reset': 5;
953
+ };
954
+ };
955
+ /**
956
+ * Build timeline event metadata from payroll context
957
+ *
958
+ * @param context - Operation context from payroll methods
959
+ * @returns Metadata object for timeline event
960
+ *
961
+ * @example
962
+ * ```typescript
963
+ * employee.addTimelineEvent(
964
+ * PAYROLL_EVENTS.EMPLOYEE.HIRED,
965
+ * 'Hired as Software Engineer',
966
+ * request,
967
+ * buildTimelineMetadata(params.context)
968
+ * );
969
+ * ```
970
+ */
971
+ declare function buildTimelineMetadata(context?: {
972
+ userId?: unknown;
973
+ userName?: string;
974
+ userRole?: string;
975
+ organizationId?: unknown;
976
+ }): Record<string, unknown>;
977
+ /**
978
+ * Build context object for timeline event (IP, user agent, etc.)
979
+ *
980
+ * @param request - Express/Fastify request object
981
+ * @returns Context object for timeline event
982
+ *
983
+ * @example
984
+ * ```typescript
985
+ * employee.addTimelineEvent(
986
+ * PAYROLL_EVENTS.COMPENSATION.SALARY_UPDATED,
987
+ * `Salary updated to ${newSalary}`,
988
+ * request,
989
+ * { previousSalary, newSalary },
990
+ * buildRequestContext(request)
991
+ * );
992
+ * ```
993
+ */
994
+ declare function buildRequestContext(request?: {
995
+ ip?: string;
996
+ headers?: Record<string, string | string[] | undefined>;
997
+ get?: (header: string) => string | undefined;
998
+ }): Record<string, unknown> | undefined;
999
+
1000
+ /**
1001
+ * @classytic/payroll - State Machine
1002
+ *
1003
+ * Minimal state machine implementation for status management.
1004
+ * Enforces valid transitions and provides clear error messages.
1005
+ */
1006
+ /**
1007
+ * State transition definition
1008
+ */
1009
+ interface StateTransition<TState extends string> {
1010
+ from: TState | TState[];
1011
+ to: TState;
1012
+ }
1013
+ /**
1014
+ * State machine configuration
1015
+ */
1016
+ interface StateMachineConfig<TState extends string> {
1017
+ /** All valid states */
1018
+ states: readonly TState[];
1019
+ /** Initial state */
1020
+ initial: TState;
1021
+ /** Valid transitions */
1022
+ transitions: StateTransition<TState>[];
1023
+ /** Terminal states (no outgoing transitions) */
1024
+ terminal?: TState[];
1025
+ }
1026
+ /**
1027
+ * Transition result
1028
+ */
1029
+ type TransitionResult<TState extends string> = {
1030
+ success: true;
1031
+ from: TState;
1032
+ to: TState;
1033
+ } | {
1034
+ success: false;
1035
+ from: TState;
1036
+ to: TState;
1037
+ error: string;
1038
+ };
1039
+ /**
1040
+ * Minimal state machine for status management
1041
+ *
1042
+ * @example
1043
+ * const machine = new StateMachine({
1044
+ * states: ['pending', 'processing', 'paid', 'voided'] as const,
1045
+ * initial: 'pending',
1046
+ * transitions: [
1047
+ * { from: 'pending', to: 'processing' },
1048
+ * { from: 'pending', to: 'voided' },
1049
+ * { from: 'processing', to: 'paid' },
1050
+ * ],
1051
+ * terminal: ['paid', 'voided'],
1052
+ * });
1053
+ *
1054
+ * machine.canTransition('pending', 'processing'); // true
1055
+ * machine.canTransition('paid', 'pending'); // false
1056
+ */
1057
+ declare class StateMachine<TState extends string> {
1058
+ private readonly config;
1059
+ private readonly validTransitions;
1060
+ private readonly terminalStates;
1061
+ constructor(config: StateMachineConfig<TState>);
1062
+ /**
1063
+ * Get the initial state
1064
+ */
1065
+ get initial(): TState;
1066
+ /**
1067
+ * Get all valid states
1068
+ */
1069
+ get states(): readonly TState[];
1070
+ /**
1071
+ * Check if a state is valid
1072
+ */
1073
+ isValidState(state: string): state is TState;
1074
+ /**
1075
+ * Check if a state is terminal (no outgoing transitions)
1076
+ */
1077
+ isTerminal(state: TState): boolean;
1078
+ /**
1079
+ * Check if transition from one state to another is valid
1080
+ */
1081
+ canTransition(from: TState, to: TState): boolean;
1082
+ /**
1083
+ * Get all valid next states from current state
1084
+ */
1085
+ getNextStates(from: TState): TState[];
1086
+ /**
1087
+ * Validate a transition and return result
1088
+ */
1089
+ validateTransition(from: TState, to: TState): TransitionResult<TState>;
1090
+ /**
1091
+ * Assert a transition is valid, throw if not
1092
+ */
1093
+ assertTransition(from: TState, to: TState): void;
1094
+ }
1095
+ /**
1096
+ * Create a state machine instance
1097
+ */
1098
+ declare function createStateMachine<TState extends string>(config: StateMachineConfig<TState>): StateMachine<TState>;
1099
+
1100
+ /**
1101
+ * @classytic/payroll - Payroll State Machines
1102
+ *
1103
+ * Defines valid state transitions for all status types.
1104
+ * Single source of truth for status management.
1105
+ */
1106
+
1107
+ /**
1108
+ * PayrollStatus state machine
1109
+ *
1110
+ * State diagram:
1111
+ * ```
1112
+ * PENDING ──┬──> PROCESSING ──┬──> PAID ──> REVERSED
1113
+ * │ │ │
1114
+ * │ │ └──> FAILED ──┐
1115
+ * │ │ │
1116
+ * │ └──> VOIDED <──────────┘
1117
+ * │ ↑
1118
+ * └──────────────┘
1119
+ * ```
1120
+ *
1121
+ * - PENDING: Initial state, payroll created but not processed
1122
+ * - PROCESSING: Currently being processed (bulk operations)
1123
+ * - PAID: Payment completed successfully
1124
+ * - FAILED: Processing failed (can retry → pending, or void)
1125
+ * - VOIDED: Cancelled before payment (can restore → pending)
1126
+ * - REVERSED: Payment reversed after completion (terminal)
1127
+ */
1128
+ declare const PayrollStatusMachine: StateMachine<"pending" | "processing" | "paid" | "failed" | "voided" | "reversed">;
1129
+ type PayrollStatusState = typeof PayrollStatusMachine.states[number];
1130
+ /**
1131
+ * TaxStatus state machine
1132
+ *
1133
+ * State diagram:
1134
+ * ```
1135
+ * PENDING ──┬──> SUBMITTED ──> PAID
1136
+ * │
1137
+ * └──> CANCELLED
1138
+ * ```
1139
+ *
1140
+ * - PENDING: Tax withheld, not yet submitted to government
1141
+ * - SUBMITTED: Submitted to tax authority, awaiting confirmation
1142
+ * - PAID: Payment confirmed by tax authority
1143
+ * - CANCELLED: Invalidated (payroll voided/reversed)
1144
+ */
1145
+ declare const TaxStatusMachine: StateMachine<"pending" | "paid" | "cancelled" | "submitted">;
1146
+ type TaxStatusState = typeof TaxStatusMachine.states[number];
1147
+ /**
1148
+ * LeaveRequestStatus state machine
1149
+ *
1150
+ * State diagram:
1151
+ * ```
1152
+ * PENDING ──┬──> APPROVED
1153
+ * │
1154
+ * ├──> REJECTED
1155
+ * │
1156
+ * └──> CANCELLED
1157
+ * ```
1158
+ */
1159
+ declare const LeaveRequestStatusMachine: StateMachine<"pending" | "approved" | "rejected" | "cancelled">;
1160
+ type LeaveRequestStatusState = typeof LeaveRequestStatusMachine.states[number];
1161
+ /**
1162
+ * EmployeeStatus state machine
1163
+ *
1164
+ * State diagram:
1165
+ * ```
1166
+ * ACTIVE ←──┬──→ ON_LEAVE
1167
+ * │
1168
+ * ├──→ SUSPENDED ──→ ACTIVE
1169
+ * │
1170
+ * └──→ TERMINATED
1171
+ * ```
1172
+ */
1173
+ declare const EmployeeStatusMachine: StateMachine<"active" | "on_leave" | "suspended" | "terminated">;
1174
+ type EmployeeStatusState = typeof EmployeeStatusMachine.states[number];
1175
+
1176
+ declare const EMPLOYMENT_TYPE: {
1177
+ readonly FULL_TIME: "full_time";
1178
+ readonly PART_TIME: "part_time";
1179
+ readonly CONTRACT: "contract";
1180
+ readonly INTERN: "intern";
1181
+ readonly CONSULTANT: "consultant";
1182
+ };
1183
+ declare const EMPLOYEE_STATUS: {
1184
+ readonly ACTIVE: "active";
1185
+ readonly ON_LEAVE: "on_leave";
1186
+ readonly SUSPENDED: "suspended";
1187
+ readonly TERMINATED: "terminated";
1188
+ };
1189
+ declare const DEPARTMENT: {
1190
+ readonly MANAGEMENT: "management";
1191
+ readonly TRAINING: "training";
1192
+ readonly SALES: "sales";
1193
+ readonly OPERATIONS: "operations";
1194
+ readonly SUPPORT: "support";
1195
+ readonly HR: "hr";
1196
+ readonly MAINTENANCE: "maintenance";
1197
+ readonly MARKETING: "marketing";
1198
+ readonly FINANCE: "finance";
1199
+ readonly IT: "it";
1200
+ };
1201
+ declare const PAYMENT_FREQUENCY: {
1202
+ readonly MONTHLY: "monthly";
1203
+ readonly BI_WEEKLY: "bi_weekly";
1204
+ readonly WEEKLY: "weekly";
1205
+ readonly HOURLY: "hourly";
1206
+ readonly DAILY: "daily";
1207
+ };
1208
+ declare const ALLOWANCE_TYPE: {
1209
+ readonly HOUSING: "housing";
1210
+ readonly TRANSPORT: "transport";
1211
+ readonly MEAL: "meal";
1212
+ readonly MOBILE: "mobile";
1213
+ readonly MEDICAL: "medical";
1214
+ readonly EDUCATION: "education";
1215
+ readonly BONUS: "bonus";
1216
+ readonly OTHER: "other";
1217
+ };
1218
+ declare const DEDUCTION_TYPE: {
1219
+ readonly TAX: "tax";
1220
+ readonly LOAN: "loan";
1221
+ readonly ADVANCE: "advance";
1222
+ readonly PROVIDENT_FUND: "provident_fund";
1223
+ readonly INSURANCE: "insurance";
1224
+ readonly ABSENCE: "absence";
1225
+ readonly OTHER: "other";
1226
+ };
1227
+ declare const PAYROLL_STATUS: {
1228
+ readonly PENDING: "pending";
1229
+ readonly PROCESSING: "processing";
1230
+ readonly PAID: "paid";
1231
+ readonly FAILED: "failed";
1232
+ readonly VOIDED: "voided";
1233
+ readonly REVERSED: "reversed";
1234
+ };
1235
+ /** Check if payroll can be voided (not yet paid) */
1236
+ declare function isVoidablePayrollStatus(status: PayrollStatus): boolean;
1237
+ /** Check if payroll requires reversal (already paid) */
1238
+ declare function requiresReversalPayrollStatus(status: PayrollStatus): boolean;
1239
+ /** Check if payroll is in a terminal void/reverse state */
1240
+ declare function isVoidedOrReversedStatus(status: PayrollStatus): boolean;
1241
+ declare const TERMINATION_REASON: {
1242
+ readonly RESIGNATION: "resignation";
1243
+ readonly RETIREMENT: "retirement";
1244
+ readonly TERMINATION: "termination";
1245
+ readonly CONTRACT_END: "contract_end";
1246
+ readonly MUTUAL_AGREEMENT: "mutual_agreement";
1247
+ readonly OTHER: "other";
1248
+ };
1249
+ declare const LEAVE_TYPE: {
1250
+ readonly ANNUAL: "annual";
1251
+ readonly SICK: "sick";
1252
+ readonly UNPAID: "unpaid";
1253
+ readonly MATERNITY: "maternity";
1254
+ readonly PATERNITY: "paternity";
1255
+ readonly BEREAVEMENT: "bereavement";
1256
+ readonly COMPENSATORY: "compensatory";
1257
+ readonly OTHER: "other";
1258
+ };
1259
+ declare function isValidLeaveType(value: string): value is LeaveType;
1260
+ declare function isPaidLeaveType(type: LeaveType): boolean;
1261
+ declare const LEAVE_REQUEST_STATUS: {
1262
+ readonly PENDING: "pending";
1263
+ readonly APPROVED: "approved";
1264
+ readonly REJECTED: "rejected";
1265
+ readonly CANCELLED: "cancelled";
1266
+ };
1267
+ declare function isValidLeaveRequestStatus(value: string): value is LeaveRequestStatus;
1268
+ declare function isPendingLeaveStatus(status: LeaveRequestStatus): boolean;
1269
+ declare function isApprovedLeaveStatus(status: LeaveRequestStatus): boolean;
1270
+ declare const TAX_TYPE: {
1271
+ readonly INCOME_TAX: "income_tax";
1272
+ readonly SOCIAL_SECURITY: "social_security";
1273
+ readonly HEALTH_INSURANCE: "health_insurance";
1274
+ readonly PENSION: "pension";
1275
+ readonly EMPLOYMENT_INSURANCE: "employment_insurance";
1276
+ readonly LOCAL_TAX: "local_tax";
1277
+ readonly OTHER: "other";
1278
+ };
1279
+ declare const TAX_TYPE_VALUES: ("other" | "income_tax" | "social_security" | "health_insurance" | "pension" | "employment_insurance" | "local_tax")[];
1280
+ declare function isValidTaxType(value: string): value is TaxType;
1281
+ declare const TAX_STATUS: {
1282
+ readonly PENDING: "pending";
1283
+ readonly SUBMITTED: "submitted";
1284
+ readonly PAID: "paid";
1285
+ readonly CANCELLED: "cancelled";
1286
+ };
1287
+ declare const TAX_STATUS_VALUES: ("pending" | "paid" | "cancelled" | "submitted")[];
1288
+ declare function isValidTaxStatus(value: string): value is TaxStatus;
1289
+ declare function isPendingTaxStatus(status: TaxStatus): boolean;
1290
+ declare function isPaidTaxStatus(status: TaxStatus): boolean;
1291
+ declare function isCancelledTaxStatus(status: TaxStatus): boolean;
1292
+
1293
+ /**
1294
+ * @classytic/payroll - Configuration
1295
+ *
1296
+ * Centralized configuration with type safety
1297
+ * Configurable defaults for different use cases
1298
+ */
1299
+
1300
+ declare const HRM_CONFIG: HRMConfig;
1301
+ /**
1302
+ * Determine the appropriate organization role for an employee
1303
+ */
1304
+ declare function determineOrgRole(employmentData: {
1305
+ department?: Department | string;
1306
+ type?: EmploymentType | string;
1307
+ position?: string;
1308
+ }): OrgRole;
1309
+ /**
1310
+ * Merge configuration with defaults
1311
+ */
1312
+ declare function mergeConfig(customConfig: Partial<HRMConfig> | DeepPartial<HRMConfig> | undefined): HRMConfig;
1313
+
1314
+ /**
1315
+ * @classytic/payroll - Employee Plugin
1316
+ *
1317
+ * Mongoose plugin that adds HRM methods and virtuals to Employee schema
1318
+ */
1319
+
1320
+ interface EmployeePluginOptions {
1321
+ /** Require bank details for salary payment */
1322
+ requireBankDetails?: boolean;
1323
+ /** Field name for compensation */
1324
+ compensationField?: string;
1325
+ /** Field name for status */
1326
+ statusField?: string;
1327
+ /** Enable auto salary calculation on save */
1328
+ autoCalculateSalary?: boolean;
1329
+ /** Create indexes on schema (default: false) */
1330
+ createIndexes?: boolean;
1331
+ /** Enable leave management methods (default: false) */
1332
+ enableLeave?: boolean;
1333
+ /** Leave configuration */
1334
+ leaveConfig?: LeaveInitConfig;
1335
+ /** Field name for leave balances (default: 'leaveBalances') */
1336
+ leaveBalancesField?: string;
1337
+ }
1338
+ /**
1339
+ * Mongoose plugin that adds HRM functionality to Employee schema
1340
+ *
1341
+ * @example
1342
+ * ```typescript
1343
+ * const employeeSchema = new Schema({
1344
+ * ...createEmploymentFields({ organizationRef: 'Branch' }),
1345
+ * // Custom fields
1346
+ * });
1347
+ *
1348
+ * employeeSchema.plugin(employeePlugin);
1349
+ * ```
1350
+ */
1351
+ declare function employeePlugin(schema: Schema, options?: EmployeePluginOptions): void;
1352
+
1353
+ /**
1354
+ * @classytic/payroll - Employee Factory
1355
+ *
1356
+ * Clean object creation for employee documents
1357
+ * Builder pattern for fluent API
1358
+ */
1359
+
1360
+ interface CreateEmployeeParams {
1361
+ userId?: ObjectIdLike;
1362
+ organizationId: ObjectIdLike;
1363
+ employment: {
1364
+ employeeId?: string;
1365
+ email?: string;
1366
+ type?: EmploymentType;
1367
+ department?: Department | string;
1368
+ position: string;
1369
+ hireDate?: Date;
1370
+ probationMonths?: number;
1371
+ workSchedule?: WorkSchedule;
1372
+ };
1373
+ compensation: {
1374
+ baseAmount: number;
1375
+ frequency?: PaymentFrequency;
1376
+ currency?: string;
1377
+ allowances?: Array<Partial<Allowance>>;
1378
+ deductions?: Array<Partial<Deduction>>;
1379
+ };
1380
+ bankDetails?: BankDetails;
1381
+ }
1382
+ interface EmployeeData {
1383
+ userId?: ObjectIdLike;
1384
+ email?: string;
1385
+ organizationId: ObjectIdLike;
1386
+ employeeId: string;
1387
+ employmentType: EmploymentType;
1388
+ status: 'active';
1389
+ department?: Department;
1390
+ position: string;
1391
+ hireDate: Date;
1392
+ probationEndDate: Date | null;
1393
+ compensation: Compensation;
1394
+ workSchedule: WorkSchedule;
1395
+ bankDetails: BankDetails;
1396
+ payrollStats: {
1397
+ totalPaid: number;
1398
+ paymentsThisYear: number;
1399
+ averageMonthly: number;
1400
+ };
1401
+ }
1402
+ interface TerminationData {
1403
+ terminatedAt: Date;
1404
+ terminationReason: TerminationReason;
1405
+ terminationNotes?: string;
1406
+ terminatedBy: {
1407
+ userId?: ObjectIdLike;
1408
+ name?: string;
1409
+ role?: string;
1410
+ };
1411
+ }
1412
+ declare class EmployeeFactory {
1413
+ /**
1414
+ * Create employee data object
1415
+ */
1416
+ static create(params: CreateEmployeeParams, config?: HRMConfig): EmployeeData;
1417
+ /**
1418
+ * Create compensation object
1419
+ */
1420
+ static createCompensation(params: {
1421
+ baseAmount: number;
1422
+ frequency?: PaymentFrequency;
1423
+ currency?: string;
1424
+ allowances?: Array<Partial<Allowance>>;
1425
+ deductions?: Array<Partial<Deduction>>;
1426
+ }, config?: HRMConfig): Compensation;
1427
+ /**
1428
+ * Create allowance object
1429
+ */
1430
+ static createAllowance(params: {
1431
+ type: Allowance['type'];
1432
+ amount: number;
1433
+ name?: string;
1434
+ isPercentage?: boolean;
1435
+ taxable?: boolean;
1436
+ recurring?: boolean;
1437
+ }): Allowance;
1438
+ /**
1439
+ * Create deduction object
1440
+ */
1441
+ static createDeduction(params: {
1442
+ type: Deduction['type'];
1443
+ amount: number;
1444
+ name?: string;
1445
+ isPercentage?: boolean;
1446
+ auto?: boolean;
1447
+ recurring?: boolean;
1448
+ description?: string;
1449
+ }): Deduction;
1450
+ /**
1451
+ * Default work schedule
1452
+ */
1453
+ static defaultWorkSchedule(): WorkSchedule;
1454
+ /**
1455
+ * Create termination data
1456
+ */
1457
+ static createTermination(params: {
1458
+ reason: TerminationReason;
1459
+ date?: Date;
1460
+ notes?: string;
1461
+ context?: {
1462
+ userId?: ObjectIdLike;
1463
+ userName?: string;
1464
+ userRole?: string;
1465
+ };
1466
+ }): TerminationData;
1467
+ }
1468
+ declare class EmployeeBuilder {
1469
+ private data;
1470
+ /**
1471
+ * Set user ID
1472
+ */
1473
+ forUser(userId: ObjectIdLike): this;
1474
+ /**
1475
+ * Set organization ID
1476
+ */
1477
+ inOrganization(organizationId: ObjectIdLike): this;
1478
+ /**
1479
+ * Set employee ID
1480
+ */
1481
+ withEmployeeId(employeeId: string): this;
1482
+ /**
1483
+ * Set department
1484
+ */
1485
+ inDepartment(department: Department): this;
1486
+ /**
1487
+ * Set position
1488
+ */
1489
+ asPosition(position: string): this;
1490
+ /**
1491
+ * Set employment type
1492
+ */
1493
+ withEmploymentType(type: EmploymentType): this;
1494
+ /**
1495
+ * Set hire date
1496
+ */
1497
+ hiredOn(date: Date): this;
1498
+ /**
1499
+ * Set probation period
1500
+ */
1501
+ withProbation(months: number): this;
1502
+ /**
1503
+ * Set work schedule
1504
+ */
1505
+ withSchedule(schedule: WorkSchedule): this;
1506
+ /**
1507
+ * Set base salary
1508
+ */
1509
+ withBaseSalary(amount: number, frequency?: PaymentFrequency, currency?: string): this;
1510
+ /**
1511
+ * Add allowance
1512
+ */
1513
+ addAllowance(type: Allowance['type'], amount: number, options?: {
1514
+ taxable?: boolean;
1515
+ recurring?: boolean;
1516
+ }): this;
1517
+ /**
1518
+ * Add deduction
1519
+ */
1520
+ addDeduction(type: Deduction['type'], amount: number, options?: {
1521
+ auto?: boolean;
1522
+ recurring?: boolean;
1523
+ description?: string;
1524
+ }): this;
1525
+ /**
1526
+ * Set bank details
1527
+ */
1528
+ withBankDetails(bankDetails: BankDetails): this;
1529
+ /**
1530
+ * Build employee data
1531
+ */
1532
+ build(config?: HRMConfig): EmployeeData;
1533
+ }
1534
+ /**
1535
+ * Create new employee builder
1536
+ */
1537
+ declare function createEmployee(): EmployeeBuilder;
1538
+
1539
+ /**
1540
+ * @classytic/payroll - Error Handling
1541
+ *
1542
+ * Custom error classes with error codes and HTTP status
1543
+ */
1544
+
1545
+ declare class PayrollError extends Error implements HttpError {
1546
+ readonly code: ErrorCode;
1547
+ readonly status: number;
1548
+ readonly context: Record<string, unknown>;
1549
+ readonly timestamp: Date;
1550
+ /**
1551
+ * Create a PayrollError.
1552
+ *
1553
+ * Supports BOTH constructor styles for backwards compatibility:
1554
+ * - new PayrollError(message, code?, status?, context?)
1555
+ * - new PayrollError(code, status, message, context?)
1556
+ */
1557
+ constructor(messageOrCode: string | ErrorCode, codeOrStatus?: ErrorCode | number, statusOrMessage?: number | string, context?: Record<string, unknown>);
1558
+ /**
1559
+ * Convert error to JSON for API responses (ClockIn-compatible shape)
1560
+ */
1561
+ toJSON(): Record<string, unknown>;
1562
+ /**
1563
+ * Check if error is operational (expected) vs programmer error
1564
+ */
1565
+ isOperational(): boolean;
1566
+ }
1567
+ /**
1568
+ * Not initialized error
1569
+ */
1570
+ declare class NotInitializedError extends PayrollError {
1571
+ constructor(message?: string);
1572
+ }
1573
+ /**
1574
+ * Employee not found error
1575
+ */
1576
+ declare class EmployeeNotFoundError extends PayrollError {
1577
+ constructor(employeeId?: string, context?: Record<string, unknown>);
1578
+ }
1579
+ /**
1580
+ * Invalid employee error
1581
+ */
1582
+ declare class InvalidEmployeeError extends PayrollError {
1583
+ constructor(message: string, context?: Record<string, unknown>);
1584
+ }
1585
+ /**
1586
+ * Duplicate payroll error
1587
+ */
1588
+ declare class DuplicatePayrollError extends PayrollError {
1589
+ constructor(employeeId: string, month: number, year: number, context?: Record<string, unknown>);
1590
+ }
1591
+ /**
1592
+ * Validation error
1593
+ */
1594
+ declare class ValidationError extends PayrollError {
1595
+ readonly errors: string[];
1596
+ constructor(errors: string | string[], context?: Record<string, unknown>);
1597
+ }
1598
+ /**
1599
+ * Employee terminated error
1600
+ */
1601
+ declare class EmployeeTerminatedError extends PayrollError {
1602
+ constructor(employeeId?: string, context?: Record<string, unknown>);
1603
+ }
1604
+ /**
1605
+ * Already processed error
1606
+ */
1607
+ declare class AlreadyProcessedError extends PayrollError {
1608
+ constructor(message: string, context?: Record<string, unknown>);
1609
+ }
1610
+ /**
1611
+ * Not eligible error
1612
+ */
1613
+ declare class NotEligibleError extends PayrollError {
1614
+ constructor(message: string, context?: Record<string, unknown>);
1615
+ }
1616
+ /**
1617
+ * Security error (unauthorized access, cross-organization access, etc.)
1618
+ */
1619
+ declare class SecurityError extends PayrollError {
1620
+ constructor(message: string, context?: Record<string, unknown>);
1621
+ }
1622
+ /**
1623
+ * Create error from code
1624
+ */
1625
+ declare function createError(code: ErrorCode, message: string, context?: Record<string, unknown>): PayrollError;
1626
+ /**
1627
+ * Check if error is PayrollError
1628
+ */
1629
+ declare function isPayrollError(error: unknown): error is PayrollError;
1630
+ /**
1631
+ * Extract error info for logging
1632
+ */
1633
+ declare function extractErrorInfo(error: unknown): {
1634
+ code: string;
1635
+ status: number;
1636
+ message: string;
1637
+ context?: Record<string, unknown>;
1638
+ };
1639
+ /**
1640
+ * Convert unknown error to PayrollError
1641
+ */
1642
+ declare function toPayrollError(error: unknown): PayrollError;
1643
+
1644
+ /**
1645
+ * @classytic/payroll - Attendance Integration
1646
+ *
1647
+ * Native integration with @classytic/clockin.
1648
+ * ClockIn is an optional peer dependency for attendance-based deductions.
1649
+ */
1650
+
1651
+ /**
1652
+ * Get attendance for payroll calculation
1653
+ *
1654
+ * @example
1655
+ * ```typescript
1656
+ * import { getAttendance } from '@classytic/payroll';
1657
+ *
1658
+ * const attendance = await getAttendance(Attendance, {
1659
+ * organizationId: org._id,
1660
+ * employeeId: emp._id,
1661
+ * month: 3,
1662
+ * year: 2024,
1663
+ * expectedDays: 22,
1664
+ * });
1665
+ *
1666
+ * await payroll.processSalary({ employeeId, month: 3, year: 2024, attendance });
1667
+ * ```
1668
+ */
1669
+ declare function getAttendance(AttendanceModel: Model<unknown>, params: {
1670
+ organizationId: ObjectIdLike;
1671
+ employeeId: ObjectIdLike;
1672
+ month: number;
1673
+ year: number;
1674
+ expectedDays: number;
1675
+ }): Promise<(AttendanceInput & {
1676
+ absentDays: number;
1677
+ overtimeDays: number;
1678
+ }) | null>;
1679
+ /**
1680
+ * Get attendance for multiple employees (efficient batch operation)
1681
+ *
1682
+ * @example
1683
+ * ```typescript
1684
+ * const attendanceMap = await batchGetAttendance(Attendance, {
1685
+ * organizationId: org._id,
1686
+ * employeeIds: [emp1._id, emp2._id, emp3._id],
1687
+ * month: 3,
1688
+ * year: 2024,
1689
+ * expectedDays: 22,
1690
+ * });
1691
+ *
1692
+ * const emp1Attendance = attendanceMap.get(emp1._id.toString());
1693
+ * ```
1694
+ */
1695
+ declare function batchGetAttendance(AttendanceModel: Model<unknown>, params: {
1696
+ organizationId: ObjectIdLike;
1697
+ employeeIds: ObjectIdLike[];
1698
+ month: number;
1699
+ year: number;
1700
+ expectedDays: number;
1701
+ }): Promise<Map<string, AttendanceInput & {
1702
+ absentDays: number;
1703
+ overtimeDays: number;
1704
+ }>>;
1705
+
1706
+ /**
1707
+ * @classytic/payroll - Holiday Management
1708
+ *
1709
+ * Simple holiday storage and retrieval.
1710
+ * ONE way to manage holidays - no confusion.
1711
+ */
1712
+
1713
+ /**
1714
+ * Holiday document
1715
+ */
1716
+ interface Holiday {
1717
+ organizationId?: any;
1718
+ date: Date;
1719
+ name: string;
1720
+ type: 'public' | 'company' | 'religious';
1721
+ paid: boolean;
1722
+ }
1723
+ /**
1724
+ * Create holiday schema
1725
+ *
1726
+ * @example
1727
+ * ```typescript
1728
+ * import { createHolidaySchema } from '@classytic/payroll';
1729
+ *
1730
+ * // Multi-tenant
1731
+ * const Holiday = model('Holiday', createHolidaySchema());
1732
+ *
1733
+ * // Single-tenant
1734
+ * const Holiday = model('Holiday', createHolidaySchema({ singleTenant: true }));
1735
+ * ```
1736
+ */
1737
+ declare function createHolidaySchema(options?: {
1738
+ singleTenant?: boolean;
1739
+ }): Schema;
1740
+ /**
1741
+ * Get holidays for a period
1742
+ *
1743
+ * @example
1744
+ * ```typescript
1745
+ * const holidays = await getHolidays(Holiday, {
1746
+ * organizationId: org._id, // optional for single-tenant
1747
+ * startDate: new Date('2024-03-01'),
1748
+ * endDate: new Date('2024-03-31'),
1749
+ * });
1750
+ * ```
1751
+ */
1752
+ declare function getHolidays(HolidayModel: Model<any>, params: {
1753
+ organizationId?: any;
1754
+ startDate: Date;
1755
+ endDate: Date;
1756
+ }): Promise<Date[]>;
1757
+
1758
+ /**
1759
+ * @classytic/payroll - Shift Compliance Types
1760
+ *
1761
+ * Clean, modern type definitions for shift-based attendance management.
1762
+ * No legacy baggage - one proper standard.
1763
+ */
1764
+
1765
+ /** How penalties are calculated */
1766
+ type PenaltyMode = 'flat' | 'per-minute' | 'percentage' | 'tiered';
1767
+ /** When overtime kicks in */
1768
+ type OvertimeMode = 'daily' | 'weekly' | 'monthly';
1769
+ /** When to reset occurrence counters */
1770
+ type ResetPeriod = 'daily' | 'weekly' | 'monthly' | 'quarterly' | 'yearly';
1771
+ /** Clock-in rounding mode */
1772
+ type RoundingMode = 'nearest' | 'up' | 'down';
1773
+ /**
1774
+ * Tiered penalty configuration for progressive discipline.
1775
+ *
1776
+ * @example
1777
+ * ```typescript
1778
+ * [
1779
+ * { from: 1, to: 2, penalty: 0, warning: true }, // 1st-2nd: warning only
1780
+ * { from: 3, to: 4, penalty: 25 }, // 3rd-4th: $25
1781
+ * { from: 5, penalty: 50 } // 5th+: $50
1782
+ * ]
1783
+ * ```
1784
+ */
1785
+ interface PenaltyTier {
1786
+ /** Occurrence number start (inclusive) */
1787
+ from: number;
1788
+ /** Occurrence number end (inclusive, optional for open-ended) */
1789
+ to?: number;
1790
+ /** Penalty amount for this tier */
1791
+ penalty: number;
1792
+ /** If true, log warning but don't deduct money */
1793
+ warning?: boolean;
1794
+ }
1795
+ /**
1796
+ * Maximum penalties per period configuration
1797
+ */
1798
+ interface MaxPenaltiesPerPeriod {
1799
+ /** Maximum number of penalties allowed */
1800
+ count: number;
1801
+ /** Period type */
1802
+ period: ResetPeriod;
1803
+ }
1804
+ /**
1805
+ * Weekend premium configuration
1806
+ */
1807
+ interface WeekendPremium {
1808
+ /** Saturday premium multiplier (e.g., 1.5 for time-and-a-half) */
1809
+ saturday: number;
1810
+ /** Sunday premium multiplier (e.g., 2.0 for double time) */
1811
+ sunday: number;
1812
+ }
1813
+ /**
1814
+ * Night shift differential configuration
1815
+ */
1816
+ interface NightShiftDifferential {
1817
+ /** Start hour (24h format, e.g., 22 = 10pm) */
1818
+ startHour: number;
1819
+ /** End hour (24h format, e.g., 6 = 6am) */
1820
+ endHour: number;
1821
+ /** Premium multiplier (e.g., 1.2 = 20% extra) */
1822
+ multiplier: number;
1823
+ }
1824
+ /**
1825
+ * Late arrival policy configuration
1826
+ */
1827
+ interface LateArrivalPolicy {
1828
+ /** Enable late arrival tracking */
1829
+ enabled: boolean;
1830
+ /** Grace period in minutes (no penalty if late < this) */
1831
+ gracePeriod: number;
1832
+ /** How to calculate penalty */
1833
+ mode: PenaltyMode;
1834
+ /** Fixed penalty amount per occurrence */
1835
+ flatAmount?: number;
1836
+ /** Penalty per minute late */
1837
+ perMinuteRate?: number;
1838
+ /** Penalty as percentage of daily wage (e.g., 2 = 2%) */
1839
+ percentageRate?: number;
1840
+ /** Progressive penalties based on occurrence count */
1841
+ tiers?: PenaltyTier[];
1842
+ /** Maximum penalties allowed per period */
1843
+ maxPenaltiesPerPeriod?: MaxPenaltiesPerPeriod;
1844
+ /** Maximum total penalty amount per period */
1845
+ maxPenaltyAmount?: {
1846
+ amount: number;
1847
+ period: ResetPeriod;
1848
+ };
1849
+ /** When to reset occurrence counter */
1850
+ resetOccurrenceCount?: ResetPeriod;
1851
+ }
1852
+ /**
1853
+ * Early departure policy configuration
1854
+ * (Same structure as late arrival)
1855
+ */
1856
+ type EarlyDeparturePolicy = LateArrivalPolicy;
1857
+ /**
1858
+ * Overtime bonus configuration
1859
+ */
1860
+ interface OvertimePolicy {
1861
+ /** Enable overtime bonuses */
1862
+ enabled: boolean;
1863
+ /** When overtime kicks in */
1864
+ mode: OvertimeMode;
1865
+ /** Hours per day before overtime (e.g., 8) */
1866
+ dailyThreshold?: number;
1867
+ /** Overtime multiplier for daily (e.g., 1.5 = time and half) */
1868
+ dailyMultiplier?: number;
1869
+ /** Hours per week before overtime (e.g., 40) */
1870
+ weeklyThreshold?: number;
1871
+ /** Overtime multiplier for weekly */
1872
+ weeklyMultiplier?: number;
1873
+ /** Hours per month before overtime (e.g., 160) */
1874
+ monthlyThreshold?: number;
1875
+ /** Overtime multiplier for monthly */
1876
+ monthlyMultiplier?: number;
1877
+ /** Weekend premium pay (null = disabled) */
1878
+ weekendPremium?: WeekendPremium;
1879
+ /** Night shift premium (null = disabled) */
1880
+ nightShiftDifferential?: NightShiftDifferential;
1881
+ }
1882
+ /**
1883
+ * Clock-in rounding configuration
1884
+ */
1885
+ interface ClockRoundingPolicy {
1886
+ /** Enable clock-in rounding */
1887
+ enabled: boolean;
1888
+ /** Round to nearest X minutes */
1889
+ roundTo: 5 | 10 | 15;
1890
+ /** Rounding mode */
1891
+ mode: RoundingMode;
1892
+ }
1893
+ /**
1894
+ * Complete attendance policy configuration.
1895
+ *
1896
+ * This is what organizations define and what we use for calculations.
1897
+ * Users can store this in DB, config file, or pass directly.
1898
+ */
1899
+ interface AttendancePolicy {
1900
+ /** Unique policy ID (optional, for DB storage) */
1901
+ id?: string;
1902
+ /** Organization this policy belongs to (optional, for multi-tenant) */
1903
+ organizationId?: ObjectIdLike;
1904
+ /** Policy name for display */
1905
+ name: string;
1906
+ /** Policy description */
1907
+ description?: string;
1908
+ /** Who this policy applies to (optional, for targeted policies) */
1909
+ appliesTo?: {
1910
+ departments?: string[];
1911
+ positions?: string[];
1912
+ employeeIds?: ObjectIdLike[];
1913
+ all?: boolean;
1914
+ };
1915
+ /** Late arrival rules */
1916
+ lateArrival: LateArrivalPolicy;
1917
+ /** Early departure rules */
1918
+ earlyDeparture: EarlyDeparturePolicy;
1919
+ /** Overtime bonus rules */
1920
+ overtime: OvertimePolicy;
1921
+ /** Clock-in rounding rules */
1922
+ clockRounding?: ClockRoundingPolicy;
1923
+ /** When this policy becomes effective */
1924
+ effectiveFrom: Date;
1925
+ /** When this policy expires (null = no expiry) */
1926
+ effectiveTo?: Date | null;
1927
+ /** Is this policy active */
1928
+ active: boolean;
1929
+ }
1930
+ /**
1931
+ * Single late arrival occurrence
1932
+ */
1933
+ interface LateOccurrence {
1934
+ /** Date of late arrival */
1935
+ date: Date;
1936
+ /** Scheduled clock-in time */
1937
+ scheduledTime: Date;
1938
+ /** Actual clock-in time */
1939
+ actualTime: Date;
1940
+ /** Minutes late (calculated: actual - scheduled) */
1941
+ minutesLate: number;
1942
+ }
1943
+ /**
1944
+ * Single early departure occurrence
1945
+ */
1946
+ interface EarlyOccurrence {
1947
+ /** Date of early departure */
1948
+ date: Date;
1949
+ /** Scheduled clock-out time */
1950
+ scheduledTime: Date;
1951
+ /** Actual clock-out time */
1952
+ actualTime: Date;
1953
+ /** Minutes early (calculated: scheduled - actual) */
1954
+ minutesEarly: number;
1955
+ }
1956
+ /**
1957
+ * Single overtime occurrence
1958
+ */
1959
+ interface OvertimeOccurrence {
1960
+ /** Date of overtime */
1961
+ date: Date;
1962
+ /** Type of overtime */
1963
+ type: 'daily' | 'weekly' | 'monthly' | 'weekend-saturday' | 'weekend-sunday' | 'night-shift';
1964
+ /** Overtime hours */
1965
+ hours: number;
1966
+ /** Applicable multiplier */
1967
+ multiplier: number;
1968
+ }
1969
+ /**
1970
+ * Shift compliance data for a period.
1971
+ *
1972
+ * This is what users send us - we do the calculations.
1973
+ */
1974
+ interface ShiftComplianceData {
1975
+ /** Number of late arrivals */
1976
+ lateArrivals?: number;
1977
+ /** Total minutes late (sum of all occurrences) */
1978
+ totalLateMinutes?: number;
1979
+ /** Detailed late occurrences (optional, for breakdown) */
1980
+ lateOccurrences?: LateOccurrence[];
1981
+ /** Number of early departures */
1982
+ earlyDepartures?: number;
1983
+ /** Total minutes early */
1984
+ totalEarlyMinutes?: number;
1985
+ /** Detailed early occurrences */
1986
+ earlyOccurrences?: EarlyOccurrence[];
1987
+ /** Total overtime hours */
1988
+ overtimeHours?: number;
1989
+ /** Total overtime days (for daily mode) */
1990
+ overtimeDays?: number;
1991
+ /** Detailed overtime breakdown */
1992
+ overtimeOccurrences?: OvertimeOccurrence[];
1993
+ }
1994
+ /**
1995
+ * Late penalty calculation result
1996
+ */
1997
+ interface LatePenaltyResult {
1998
+ /** Total penalty amount */
1999
+ amount: number;
2000
+ /** Number of occurrences processed */
2001
+ occurrences: number;
2002
+ /** Breakdown per occurrence */
2003
+ breakdown: Array<{
2004
+ date: Date;
2005
+ minutesLate: number;
2006
+ penaltyAmount: number;
2007
+ tier?: number;
2008
+ waived: boolean;
2009
+ reason?: string;
2010
+ }>;
2011
+ }
2012
+ /**
2013
+ * Early departure penalty result
2014
+ */
2015
+ type EarlyDeparturePenaltyResult = LatePenaltyResult;
2016
+ /**
2017
+ * Overtime bonus calculation result
2018
+ */
2019
+ interface OvertimeBonusResult {
2020
+ /** Total bonus amount */
2021
+ amount: number;
2022
+ /** Total overtime hours */
2023
+ hours: number;
2024
+ /** Breakdown by type */
2025
+ breakdown: Array<{
2026
+ date: Date;
2027
+ type: string;
2028
+ hours: number;
2029
+ rate: number;
2030
+ multiplier: number;
2031
+ amount: number;
2032
+ }>;
2033
+ }
2034
+ /**
2035
+ * Shift differential calculation result
2036
+ */
2037
+ interface ShiftDifferentialResult {
2038
+ /** Total differential amount */
2039
+ amount: number;
2040
+ /** Hours that qualify for differential */
2041
+ hours: number;
2042
+ /** Type of differential */
2043
+ type: 'night' | 'weekend';
2044
+ /** Multiplier applied */
2045
+ multiplier: number;
2046
+ }
2047
+ /**
2048
+ * Complete shift compliance calculation result.
2049
+ *
2050
+ * This is what we return after processing.
2051
+ */
2052
+ interface ShiftComplianceResult {
2053
+ /** Late arrival penalties */
2054
+ latePenalty: LatePenaltyResult;
2055
+ /** Early departure penalties */
2056
+ earlyDeparturePenalty: EarlyDeparturePenaltyResult;
2057
+ /** Overtime bonuses */
2058
+ overtimeBonus: OvertimeBonusResult;
2059
+ /** Shift differential bonuses (if any) */
2060
+ shiftDifferential?: ShiftDifferentialResult;
2061
+ /** Total penalties (to deduct from salary) */
2062
+ totalPenalties: number;
2063
+ /** Total bonuses (to add to salary) */
2064
+ totalBonuses: number;
2065
+ /** Net adjustment (bonuses - penalties) */
2066
+ netAdjustment: number;
2067
+ /** Compliance score (0-100) */
2068
+ complianceScore: number;
2069
+ /** Total occurrence count (late + early) */
2070
+ occurrenceCount: number;
2071
+ /** Is employee at risk (near termination threshold) */
2072
+ isAtRisk: boolean;
2073
+ /** Policy ID that was used */
2074
+ policyId?: string;
2075
+ /** Policy name */
2076
+ policyName: string;
2077
+ }
2078
+ /**
2079
+ * Input for shift compliance calculation
2080
+ */
2081
+ interface CalculateShiftComplianceInput {
2082
+ /** Attendance data for the period */
2083
+ attendance: ShiftComplianceData;
2084
+ /** Policy to apply */
2085
+ policy: AttendancePolicy;
2086
+ /** Daily wage (for percentage-based penalties) */
2087
+ dailyWage: number;
2088
+ /** Hourly rate (for overtime calculations) */
2089
+ hourlyRate: number;
2090
+ /** Current occurrence count (for tiered penalties, optional) */
2091
+ currentOccurrenceCount?: number;
2092
+ /** Employee ID (for logging, optional) */
2093
+ employeeId?: ObjectIdLike;
2094
+ /** Period info (for logging, optional) */
2095
+ period?: {
2096
+ month: number;
2097
+ year: number;
2098
+ };
2099
+ }
2100
+ /**
2101
+ * Manager override for waiving penalties
2102
+ */
2103
+ interface PenaltyOverride {
2104
+ /** Which penalty to override */
2105
+ penaltyId: string;
2106
+ /** Employee affected */
2107
+ employeeId: ObjectIdLike;
2108
+ /** Manager who made the override */
2109
+ overriddenBy: ObjectIdLike;
2110
+ /** When the override was made */
2111
+ overriddenAt: Date;
2112
+ /** Original penalty amount */
2113
+ originalAmount: number;
2114
+ /** New amount (0 = fully waived) */
2115
+ newAmount: number;
2116
+ /** Reason for override */
2117
+ reason: string;
2118
+ /** Does this need approval */
2119
+ approvalRequired?: boolean;
2120
+ /** Who approved (if approval required) */
2121
+ approvedBy?: ObjectIdLike;
2122
+ /** When approved */
2123
+ approvedAt?: Date;
2124
+ }
2125
+
2126
+ /**
2127
+ * @classytic/payroll - Late Penalty Calculator
2128
+ *
2129
+ * Pure functions for calculating late arrival penalties.
2130
+ * No side effects, no DB calls - just math.
2131
+ */
2132
+
2133
+ /**
2134
+ * Calculate penalty using flat rate per occurrence
2135
+ *
2136
+ * @example
2137
+ * ```typescript
2138
+ * // $50 per late occurrence
2139
+ * const result = calculateFlatPenalty(3, 50);
2140
+ * // → { amount: 150, occurrences: 3 }
2141
+ * ```
2142
+ */
2143
+ declare function calculateFlatPenalty(occurrenceCount: number, flatAmount: number): {
2144
+ amount: number;
2145
+ occurrences: number;
2146
+ };
2147
+ /**
2148
+ * Calculate penalty based on minutes late
2149
+ *
2150
+ * @example
2151
+ * ```typescript
2152
+ * // $2 per minute, 45 minutes late
2153
+ * const result = calculatePerMinutePenalty(45, 2);
2154
+ * // → { amount: 90, minutes: 45 }
2155
+ * ```
2156
+ */
2157
+ declare function calculatePerMinutePenalty(totalMinutesLate: number, perMinuteRate: number): {
2158
+ amount: number;
2159
+ minutes: number;
2160
+ };
2161
+ /**
2162
+ * Calculate penalty as percentage of daily wage
2163
+ *
2164
+ * @example
2165
+ * ```typescript
2166
+ * // 2% of $500 daily wage, 3 late occurrences
2167
+ * const result = calculatePercentagePenalty(3, 2, 500);
2168
+ * // → { amount: 30, percentage: 2 }
2169
+ * ```
2170
+ */
2171
+ declare function calculatePercentagePenalty(occurrenceCount: number, percentageRate: number, dailyWage: number): {
2172
+ amount: number;
2173
+ percentage: number;
2174
+ };
2175
+ /**
2176
+ * Calculate total tiered penalties for multiple occurrences
2177
+ *
2178
+ * @example
2179
+ * ```typescript
2180
+ * const tiers = [
2181
+ * { from: 1, to: 2, penalty: 0, warning: true },
2182
+ * { from: 3, to: 4, penalty: 25 },
2183
+ * { from: 5, penalty: 50 },
2184
+ * ];
2185
+ *
2186
+ * // Employee has 5 late occurrences
2187
+ * const result = calculateTieredPenalty(5, 2, tiers);
2188
+ * // → {
2189
+ * // amount: 125, // 0 + 0 + 25 + 25 + 50
2190
+ * // breakdown: [...]
2191
+ * // }
2192
+ * ```
2193
+ */
2194
+ declare function calculateTieredPenalty(newOccurrences: number, currentOccurrenceCount: number, tiers: PenaltyTier[]): {
2195
+ amount: number;
2196
+ breakdown: Array<{
2197
+ occurrence: number;
2198
+ penalty: number;
2199
+ tier?: number;
2200
+ warning: boolean;
2201
+ }>;
2202
+ };
2203
+ /**
2204
+ * Calculate late arrival penalties based on policy
2205
+ *
2206
+ * @example
2207
+ * ```typescript
2208
+ * const policy: LateArrivalPolicy = {
2209
+ * enabled: true,
2210
+ * gracePeriod: 5,
2211
+ * mode: 'flat',
2212
+ * flatAmount: 50,
2213
+ * };
2214
+ *
2215
+ * const occurrences: LateOccurrence[] = [
2216
+ * { date: new Date(), scheduledTime, actualTime, minutesLate: 10 },
2217
+ * { date: new Date(), scheduledTime, actualTime, minutesLate: 3 }, // Within grace
2218
+ * ];
2219
+ *
2220
+ * const result = calculateLatePenalty({
2221
+ * policy,
2222
+ * occurrences,
2223
+ * dailyWage: 500,
2224
+ * });
2225
+ * // → { amount: 50, occurrences: 1, breakdown: [...] }
2226
+ * ```
2227
+ */
2228
+ declare function calculateLatePenalty(input: {
2229
+ policy: LateArrivalPolicy;
2230
+ occurrences?: LateOccurrence[];
2231
+ lateCount?: number;
2232
+ totalLateMinutes?: number;
2233
+ dailyWage?: number;
2234
+ currentOccurrenceCount?: number;
2235
+ }): LatePenaltyResult;
2236
+
2237
+ /**
2238
+ * @classytic/payroll - Overtime Calculator
2239
+ *
2240
+ * Pure functions for calculating overtime bonuses.
2241
+ * No side effects, no DB calls - just math.
2242
+ */
2243
+
2244
+ /**
2245
+ * Calculate daily overtime bonus
2246
+ *
2247
+ * @example
2248
+ * ```typescript
2249
+ * // Employee worked 10 hours, threshold is 8, rate is $100/hour
2250
+ * const result = calculateDailyOvertime(10, 8, 1.5, 100);
2251
+ * // → { amount: 100, overtimeHours: 2 }
2252
+ * // Calculation: 2 hours × $100 × 0.5 (extra) = $100
2253
+ * ```
2254
+ */
2255
+ declare function calculateDailyOvertime(hoursWorked: number, threshold: number, multiplier: number, hourlyRate: number): {
2256
+ amount: number;
2257
+ overtimeHours: number;
2258
+ };
2259
+ /**
2260
+ * Calculate weekly overtime bonus
2261
+ *
2262
+ * @example
2263
+ * ```typescript
2264
+ * // Employee worked 45 hours, threshold is 40, rate is $100/hour
2265
+ * const result = calculateWeeklyOvertime(45, 40, 1.5, 100);
2266
+ * // → { amount: 250, overtimeHours: 5 }
2267
+ * ```
2268
+ */
2269
+ declare function calculateWeeklyOvertime(hoursWorked: number, threshold: number, multiplier: number, hourlyRate: number): {
2270
+ amount: number;
2271
+ overtimeHours: number;
2272
+ };
2273
+ /**
2274
+ * Calculate monthly overtime bonus
2275
+ *
2276
+ * @example
2277
+ * ```typescript
2278
+ * // Employee worked 170 hours, threshold is 160
2279
+ * const result = calculateMonthlyOvertime(170, 160, 1.5, 100);
2280
+ * // → { amount: 500, overtimeHours: 10 }
2281
+ * ```
2282
+ */
2283
+ declare function calculateMonthlyOvertime(hoursWorked: number, threshold: number, multiplier: number, hourlyRate: number): {
2284
+ amount: number;
2285
+ overtimeHours: number;
2286
+ };
2287
+ /**
2288
+ * Calculate weekend premium pay
2289
+ *
2290
+ * @example
2291
+ * ```typescript
2292
+ * // Employee worked 8 hours on Saturday
2293
+ * const result = calculateWeekendPremium(8, 1.5, 100, 'saturday');
2294
+ * // → { amount: 400, hours: 8 }
2295
+ * // Regular: 8 × $100 = $800
2296
+ * // Premium: 8 × $100 × 0.5 (extra) = $400
2297
+ * ```
2298
+ */
2299
+ declare function calculateWeekendPremium(hours: number, multiplier: number, hourlyRate: number, day: 'saturday' | 'sunday'): {
2300
+ amount: number;
2301
+ hours: number;
2302
+ day: string;
2303
+ };
2304
+ /**
2305
+ * Calculate night shift differential
2306
+ *
2307
+ * @example
2308
+ * ```typescript
2309
+ * // Employee worked 8 hours during night shift (10pm-6am)
2310
+ * const result = calculateNightShiftDifferential(8, 1.2, 100);
2311
+ * // → { amount: 160, hours: 8 }
2312
+ * // Differential: 8 × $100 × 0.2 (extra) = $160
2313
+ * ```
2314
+ */
2315
+ declare function calculateNightShiftDifferential(hours: number, multiplier: number, hourlyRate: number): {
2316
+ amount: number;
2317
+ hours: number;
2318
+ };
2319
+ /**
2320
+ * Calculate all overtime bonuses based on policy
2321
+ *
2322
+ * @example
2323
+ * ```typescript
2324
+ * const policy: OvertimePolicy = {
2325
+ * enabled: true,
2326
+ * mode: 'daily',
2327
+ * dailyThreshold: 8,
2328
+ * dailyMultiplier: 1.5,
2329
+ * };
2330
+ *
2331
+ * const occurrences: OvertimeOccurrence[] = [
2332
+ * { date: new Date(), type: 'daily', hours: 2, multiplier: 1.5 },
2333
+ * { date: new Date(), type: 'weekend-sunday', hours: 8, multiplier: 2.0 },
2334
+ * ];
2335
+ *
2336
+ * const result = calculateOvertimeBonus({
2337
+ * policy,
2338
+ * occurrences,
2339
+ * hourlyRate: 100,
2340
+ * });
2341
+ * ```
2342
+ */
2343
+ declare function calculateOvertimeBonus(input: {
2344
+ policy: OvertimePolicy;
2345
+ occurrences?: OvertimeOccurrence[];
2346
+ overtimeHours?: number;
2347
+ overtimeDays?: number;
2348
+ hourlyRate: number;
2349
+ }): OvertimeBonusResult;
2350
+
2351
+ /**
2352
+ * @classytic/payroll - Shift Compliance Calculators
2353
+ *
2354
+ * Main calculator that orchestrates all shift compliance calculations.
2355
+ */
2356
+
2357
+ /**
2358
+ * Calculate complete shift compliance adjustments.
2359
+ *
2360
+ * This is the main function users call. It takes attendance data + policy
2361
+ * and returns penalties + bonuses.
2362
+ *
2363
+ * @example
2364
+ * ```typescript
2365
+ * const attendance: ShiftComplianceData = {
2366
+ * lateArrivals: 3,
2367
+ * totalLateMinutes: 45,
2368
+ * earlyDepartures: 1,
2369
+ * totalEarlyMinutes: 20,
2370
+ * overtimeHours: 8,
2371
+ * };
2372
+ *
2373
+ * const policy: AttendancePolicy = {
2374
+ * name: 'Manufacturing Policy',
2375
+ * lateArrival: {
2376
+ * enabled: true,
2377
+ * gracePeriod: 0,
2378
+ * mode: 'flat',
2379
+ * flatAmount: 50,
2380
+ * },
2381
+ * earlyDeparture: {
2382
+ * enabled: true,
2383
+ * gracePeriod: 0,
2384
+ * mode: 'flat',
2385
+ * flatAmount: 75,
2386
+ * },
2387
+ * overtime: {
2388
+ * enabled: true,
2389
+ * mode: 'daily',
2390
+ * dailyThreshold: 8,
2391
+ * dailyMultiplier: 1.5,
2392
+ * },
2393
+ * effectiveFrom: new Date(),
2394
+ * active: true,
2395
+ * };
2396
+ *
2397
+ * const result = calculateShiftCompliance({
2398
+ * attendance,
2399
+ * policy,
2400
+ * dailyWage: 1500,
2401
+ * hourlyRate: 200,
2402
+ * });
2403
+ *
2404
+ * // result = {
2405
+ * // latePenalty: { amount: 150, ... },
2406
+ * // earlyDeparturePenalty: { amount: 75, ... },
2407
+ * // overtimeBonus: { amount: 800, ... },
2408
+ * // totalPenalties: 225,
2409
+ * // totalBonuses: 800,
2410
+ * // netAdjustment: 575, // +800 - 225
2411
+ * // ...
2412
+ * // }
2413
+ * ```
2414
+ */
2415
+ declare function calculateShiftCompliance(input: CalculateShiftComplianceInput): ShiftComplianceResult;
2416
+
2417
+ /**
2418
+ * @classytic/payroll - Shift Compliance Configuration
2419
+ *
2420
+ * Default configurations and industry-standard preset policies.
2421
+ */
2422
+
2423
+ /**
2424
+ * Default attendance policy (moderate, office-friendly)
2425
+ */
2426
+ declare const DEFAULT_ATTENDANCE_POLICY: Omit<AttendancePolicy, 'name' | 'effectiveFrom' | 'active'>;
2427
+ /**
2428
+ * Manufacturing/Factory policy (strict, zero tolerance)
2429
+ */
2430
+ declare const MANUFACTURING_POLICY: Omit<AttendancePolicy, 'name' | 'effectiveFrom' | 'active'>;
2431
+ /**
2432
+ * Retail policy (flexible with weekend premiums)
2433
+ */
2434
+ declare const RETAIL_POLICY: Omit<AttendancePolicy, 'name' | 'effectiveFrom' | 'active'>;
2435
+ /**
2436
+ * Office/Tech policy (very flexible, progressive discipline)
2437
+ */
2438
+ declare const OFFICE_POLICY: Omit<AttendancePolicy, 'name' | 'effectiveFrom' | 'active'>;
2439
+ /**
2440
+ * Healthcare policy (night shift differential, weekend premiums)
2441
+ */
2442
+ declare const HEALTHCARE_POLICY: Omit<AttendancePolicy, 'name' | 'effectiveFrom' | 'active'>;
2443
+ /**
2444
+ * Hospitality policy (flexible, weekend/night premiums)
2445
+ */
2446
+ declare const HOSPITALITY_POLICY: Omit<AttendancePolicy, 'name' | 'effectiveFrom' | 'active'>;
2447
+ /**
2448
+ * Get a complete policy from a preset
2449
+ *
2450
+ * @example
2451
+ * ```typescript
2452
+ * const policy = createPolicyFromPreset('manufacturing', {
2453
+ * name: 'Factory Floor Policy',
2454
+ * organizationId: orgId,
2455
+ * });
2456
+ * ```
2457
+ */
2458
+ declare function createPolicyFromPreset(preset: 'default' | 'manufacturing' | 'retail' | 'office' | 'healthcare' | 'hospitality', overrides?: Partial<AttendancePolicy>): AttendancePolicy;
2459
+
2460
+ /**
2461
+ * @classytic/payroll - Shift Compliance Fluent Builders
2462
+ *
2463
+ * DX-friendly fluent API for creating attendance policies programmatically.
2464
+ *
2465
+ * @example
2466
+ * ```typescript
2467
+ * const policy = AttendancePolicyBuilder.create()
2468
+ * .named('Tech Department Policy')
2469
+ * .description('Flexible policy for tech workers')
2470
+ * .lateArrival()
2471
+ * .enable()
2472
+ * .gracePeriod(15)
2473
+ * .tieredPenalty()
2474
+ * .tier(1, 3).warning()
2475
+ * .tier(4, 5).penalty(20)
2476
+ * .tier(6).penalty(40)
2477
+ * .end()
2478
+ * .maxPenalties(3, 'monthly')
2479
+ * .resetOccurrences('quarterly')
2480
+ * .end()
2481
+ * .overtime()
2482
+ * .enable()
2483
+ * .mode('weekly')
2484
+ * .weeklyThreshold(40, 1.5)
2485
+ * .end()
2486
+ * .build();
2487
+ * ```
2488
+ */
2489
+
2490
+ /**
2491
+ * Builder for late arrival or early departure policies.
2492
+ * Uses same structure for both since the logic is identical.
2493
+ */
2494
+ declare class LatePolicyBuilder<TParent = unknown> {
2495
+ private policy;
2496
+ private parent?;
2497
+ constructor(parent?: TParent);
2498
+ /**
2499
+ * Enable this policy
2500
+ */
2501
+ enable(): this;
2502
+ /**
2503
+ * Disable this policy
2504
+ */
2505
+ disable(): this;
2506
+ /**
2507
+ * Set grace period in minutes (how many minutes late before penalty applies)
2508
+ */
2509
+ gracePeriod(minutes: number): this;
2510
+ /**
2511
+ * Use flat penalty mode (same penalty for each occurrence)
2512
+ *
2513
+ * @param amount - Penalty amount per occurrence
2514
+ */
2515
+ flatPenalty(amount: number): this;
2516
+ /**
2517
+ * Use per-minute penalty mode (penalty based on minutes late)
2518
+ *
2519
+ * @param rate - Penalty per minute late
2520
+ */
2521
+ perMinutePenalty(rate: number): this;
2522
+ /**
2523
+ * Use percentage penalty mode (percentage of daily wage)
2524
+ *
2525
+ * @param percentage - Percentage of daily wage (e.g., 2 for 2%)
2526
+ */
2527
+ percentagePenalty(percentage: number): this;
2528
+ /**
2529
+ * Start building tiered penalty (progressive discipline)
2530
+ *
2531
+ * @example
2532
+ * ```typescript
2533
+ * .tieredPenalty()
2534
+ * .tier(1, 2).warning()
2535
+ * .tier(3, 4).penalty(25)
2536
+ * .tier(5).penalty(50)
2537
+ * .end()
2538
+ * ```
2539
+ */
2540
+ tieredPenalty(): TieredPenaltyBuilder<this>;
2541
+ /**
2542
+ * Set maximum penalties per period (caps total penalties)
2543
+ *
2544
+ * @param count - Max number of penalties
2545
+ * @param period - Period type ('daily' | 'weekly' | 'monthly' | 'quarterly' | 'yearly')
2546
+ */
2547
+ maxPenalties(count: number, period: 'daily' | 'weekly' | 'monthly' | 'quarterly' | 'yearly'): this;
2548
+ /**
2549
+ * Set when to reset occurrence counter
2550
+ *
2551
+ * @param period - Reset period ('monthly' | 'quarterly' | 'yearly')
2552
+ */
2553
+ resetOccurrences(period: 'monthly' | 'quarterly' | 'yearly'): this;
2554
+ /**
2555
+ * Add a custom tier (advanced usage)
2556
+ */
2557
+ addTier(tier: PenaltyTier): this;
2558
+ /**
2559
+ * Finish building this policy and return to parent builder
2560
+ */
2561
+ end(): TParent;
2562
+ /**
2563
+ * Build the policy (for standalone usage)
2564
+ */
2565
+ build(): LateArrivalPolicy;
2566
+ /** @internal */
2567
+ _getPolicy(): Partial<LateArrivalPolicy>;
2568
+ }
2569
+ /**
2570
+ * Builder for tiered penalties (progressive discipline)
2571
+ */
2572
+ declare class TieredPenaltyBuilder<TParent> {
2573
+ private tiers;
2574
+ private parent;
2575
+ private currentTier;
2576
+ constructor(parent: TParent);
2577
+ /**
2578
+ * Start a new tier
2579
+ *
2580
+ * @param from - Starting occurrence number (1-indexed)
2581
+ * @param to - Ending occurrence number (optional, omit for open-ended tier)
2582
+ */
2583
+ tier(from: number, to?: number): this;
2584
+ /**
2585
+ * Set this tier as warning only (no financial penalty)
2586
+ */
2587
+ warning(): this;
2588
+ /**
2589
+ * Set penalty amount for this tier
2590
+ */
2591
+ penalty(amount: number): this;
2592
+ /**
2593
+ * Finish building tiers and return to parent
2594
+ */
2595
+ end(): TParent;
2596
+ private saveTier;
2597
+ }
2598
+ /**
2599
+ * Builder for overtime policies
2600
+ */
2601
+ declare class OvertimePolicyBuilder<TParent = unknown> {
2602
+ private policy;
2603
+ private parent?;
2604
+ constructor(parent?: TParent);
2605
+ /**
2606
+ * Enable overtime calculations
2607
+ */
2608
+ enable(): this;
2609
+ /**
2610
+ * Disable overtime calculations
2611
+ */
2612
+ disable(): this;
2613
+ /**
2614
+ * Set overtime calculation mode
2615
+ */
2616
+ mode(mode: 'daily' | 'weekly' | 'monthly'): this;
2617
+ /**
2618
+ * Set daily overtime threshold and multiplier
2619
+ *
2620
+ * @param hours - Hours threshold (e.g., 8)
2621
+ * @param multiplier - Overtime multiplier (e.g., 1.5 for time-and-a-half)
2622
+ */
2623
+ dailyThreshold(hours: number, multiplier: number): this;
2624
+ /**
2625
+ * Set weekly overtime threshold and multiplier
2626
+ *
2627
+ * @param hours - Hours threshold (e.g., 40)
2628
+ * @param multiplier - Overtime multiplier (e.g., 1.5 for time-and-a-half)
2629
+ */
2630
+ weeklyThreshold(hours: number, multiplier: number): this;
2631
+ /**
2632
+ * Set monthly overtime threshold and multiplier
2633
+ *
2634
+ * @param hours - Hours threshold (e.g., 160)
2635
+ * @param multiplier - Overtime multiplier (e.g., 2.0 for double time)
2636
+ */
2637
+ monthlyThreshold(hours: number, multiplier: number): this;
2638
+ /**
2639
+ * Set weekend premium rates
2640
+ *
2641
+ * @param saturday - Saturday multiplier (e.g., 1.5)
2642
+ * @param sunday - Sunday multiplier (e.g., 2.0)
2643
+ */
2644
+ weekendPremium(saturday: number, sunday: number): this;
2645
+ /**
2646
+ * Set night shift differential
2647
+ *
2648
+ * @param startHour - Start hour (24-hour format, e.g., 22 for 10pm)
2649
+ * @param endHour - End hour (24-hour format, e.g., 6 for 6am)
2650
+ * @param multiplier - Night shift multiplier (e.g., 1.3 for 30% premium)
2651
+ */
2652
+ nightShiftDifferential(startHour: number, endHour: number, multiplier: number): this;
2653
+ /**
2654
+ * Finish building this policy and return to parent builder
2655
+ */
2656
+ end(): TParent;
2657
+ /**
2658
+ * Build the policy (for standalone usage)
2659
+ */
2660
+ build(): OvertimePolicy;
2661
+ /** @internal */
2662
+ _getPolicy(): Partial<OvertimePolicy>;
2663
+ }
2664
+ /**
2665
+ * Builder for clock rounding policies
2666
+ */
2667
+ declare class ClockRoundingPolicyBuilder<TParent = unknown> {
2668
+ private policy;
2669
+ private parent?;
2670
+ constructor(parent?: TParent);
2671
+ /**
2672
+ * Enable clock rounding
2673
+ */
2674
+ enable(): this;
2675
+ /**
2676
+ * Disable clock rounding
2677
+ */
2678
+ disable(): this;
2679
+ /**
2680
+ * Set rounding interval in minutes
2681
+ *
2682
+ * @param minutes - Round to nearest N minutes (e.g., 5, 10, 15)
2683
+ */
2684
+ roundTo(minutes: 5 | 10 | 15): this;
2685
+ /**
2686
+ * Set rounding mode
2687
+ *
2688
+ * @param mode - 'up' (favor employee) | 'down' (favor employer) | 'nearest' (neutral)
2689
+ */
2690
+ roundingMode(mode: 'up' | 'down' | 'nearest'): this;
2691
+ /**
2692
+ * Finish building this policy and return to parent builder
2693
+ */
2694
+ end(): TParent;
2695
+ /**
2696
+ * Build the policy (for standalone usage)
2697
+ */
2698
+ build(): ClockRoundingPolicy;
2699
+ /** @internal */
2700
+ _getPolicy(): Partial<ClockRoundingPolicy>;
2701
+ }
2702
+ /**
2703
+ * Main builder for creating complete attendance policies
2704
+ *
2705
+ * @example
2706
+ * ```typescript
2707
+ * const policy = AttendancePolicyBuilder.create()
2708
+ * .named('Manufacturing Policy')
2709
+ * .description('Strict policy for factory floor')
2710
+ * .organizationId(orgId)
2711
+ * .lateArrival()
2712
+ * .enable()
2713
+ * .gracePeriod(0)
2714
+ * .flatPenalty(100)
2715
+ * .maxPenalties(5, 'monthly')
2716
+ * .resetOccurrences('quarterly')
2717
+ * .end()
2718
+ * .earlyDeparture()
2719
+ * .enable()
2720
+ * .gracePeriod(0)
2721
+ * .flatPenalty(150)
2722
+ * .end()
2723
+ * .overtime()
2724
+ * .enable()
2725
+ * .mode('daily')
2726
+ * .dailyThreshold(8, 1.5)
2727
+ * .weeklyThreshold(40, 2.0)
2728
+ * .end()
2729
+ * .clockRounding()
2730
+ * .enable()
2731
+ * .roundTo(15)
2732
+ * .roundingMode('down')
2733
+ * .end()
2734
+ * .effectiveFrom(new Date('2025-01-01'))
2735
+ * .build();
2736
+ * ```
2737
+ */
2738
+ declare class AttendancePolicyBuilder {
2739
+ private policy;
2740
+ private lateArrivalBuilder?;
2741
+ private earlyDepartureBuilder?;
2742
+ private overtimeBuilder?;
2743
+ private clockRoundingBuilder?;
2744
+ /**
2745
+ * Create a new policy builder
2746
+ */
2747
+ static create(): AttendancePolicyBuilder;
2748
+ /**
2749
+ * Set policy name
2750
+ */
2751
+ named(name: string): this;
2752
+ /**
2753
+ * Set policy description
2754
+ */
2755
+ description(description: string): this;
2756
+ /**
2757
+ * Set organization ID (for multi-tenant systems)
2758
+ */
2759
+ organizationId(id: ObjectIdLike): this;
2760
+ /**
2761
+ * Set policy ID (for updates)
2762
+ */
2763
+ id(id: string): this;
2764
+ /**
2765
+ * Set effective from date
2766
+ */
2767
+ effectiveFrom(date: Date): this;
2768
+ /**
2769
+ * Set effective to date (when policy expires)
2770
+ */
2771
+ effectiveTo(date: Date | null): this;
2772
+ /**
2773
+ * Set policy active status
2774
+ */
2775
+ active(active: boolean): this;
2776
+ /**
2777
+ * Start building late arrival policy
2778
+ */
2779
+ lateArrival(): LatePolicyBuilder<this>;
2780
+ /**
2781
+ * Start building early departure policy
2782
+ */
2783
+ earlyDeparture(): LatePolicyBuilder<this>;
2784
+ /**
2785
+ * Start building overtime policy
2786
+ */
2787
+ overtime(): OvertimePolicyBuilder<this>;
2788
+ /**
2789
+ * Start building clock rounding policy
2790
+ */
2791
+ clockRounding(): ClockRoundingPolicyBuilder<this>;
2792
+ /**
2793
+ * Build the complete attendance policy
2794
+ */
2795
+ build(): AttendancePolicy;
2796
+ }
2797
+ /**
2798
+ * Create a standalone late arrival policy builder
2799
+ */
2800
+ declare function createLatePolicyBuilder(): LatePolicyBuilder<void>;
2801
+ /**
2802
+ * Create a standalone overtime policy builder
2803
+ */
2804
+ declare function createOvertimePolicyBuilder(): OvertimePolicyBuilder<void>;
2805
+ /**
2806
+ * Create a standalone clock rounding policy builder
2807
+ */
2808
+ declare function createClockRoundingPolicyBuilder(): ClockRoundingPolicyBuilder<void>;
2809
+
2810
+ /**
2811
+ * Schema definition for penalty tiers (progressive discipline)
2812
+ */
2813
+ declare const PenaltyTierSchemaDefinition: SchemaDefinition;
2814
+ /**
2815
+ * Schema for penalty tiers
2816
+ */
2817
+ declare const PenaltyTierSchema: Schema;
2818
+ /**
2819
+ * Schema definition for max penalties per period
2820
+ */
2821
+ declare const MaxPenaltiesSchemaDefinition: SchemaDefinition;
2822
+ /**
2823
+ * Schema for max penalties per period
2824
+ */
2825
+ declare const MaxPenaltiesSchema: Schema;
2826
+ /**
2827
+ * Schema definition for late arrival policy
2828
+ */
2829
+ declare const LateArrivalPolicySchemaDefinition: SchemaDefinition;
2830
+ /**
2831
+ * Schema for late arrival policy
2832
+ */
2833
+ declare const LateArrivalPolicySchema: Schema;
2834
+ /**
2835
+ * Schema definition for early departure policy
2836
+ * (Same structure as late arrival policy)
2837
+ */
2838
+ declare const EarlyDeparturePolicySchemaDefinition: {
2839
+ [path: string]: mongoose.SchemaDefinitionProperty<undefined, any, any>;
2840
+ };
2841
+ /**
2842
+ * Schema for early departure policy
2843
+ */
2844
+ declare const EarlyDeparturePolicySchema: Schema;
2845
+ /**
2846
+ * Schema definition for weekend premium
2847
+ */
2848
+ declare const WeekendPremiumSchemaDefinition: SchemaDefinition;
2849
+ /**
2850
+ * Schema for weekend premium
2851
+ */
2852
+ declare const WeekendPremiumSchema: Schema;
2853
+ /**
2854
+ * Schema definition for night shift differential
2855
+ */
2856
+ declare const NightShiftDifferentialSchemaDefinition: SchemaDefinition;
2857
+ /**
2858
+ * Schema for night shift differential
2859
+ */
2860
+ declare const NightShiftDifferentialSchema: Schema;
2861
+ /**
2862
+ * Schema definition for overtime policy
2863
+ */
2864
+ declare const OvertimePolicySchemaDefinition: SchemaDefinition;
2865
+ /**
2866
+ * Schema for overtime policy
2867
+ */
2868
+ declare const OvertimePolicySchema: Schema;
2869
+ /**
2870
+ * Schema definition for clock rounding policy
2871
+ */
2872
+ declare const ClockRoundingPolicySchemaDefinition: SchemaDefinition;
2873
+ /**
2874
+ * Schema for clock rounding policy
2875
+ */
2876
+ declare const ClockRoundingPolicySchema: Schema;
2877
+ /**
2878
+ * Schema definition for attendance policy
2879
+ *
2880
+ * Users can extend this with their own fields:
2881
+ * ```typescript
2882
+ * const CustomPolicySchema = new Schema({
2883
+ * ...AttendancePolicySchemaDefinition,
2884
+ * approvedBy: { type: Schema.Types.ObjectId, ref: 'User' },
2885
+ * department: String,
2886
+ * });
2887
+ * ```
2888
+ */
2889
+ declare const AttendancePolicySchemaDefinition: SchemaDefinition;
2890
+ /**
2891
+ * Main Attendance Policy Schema
2892
+ *
2893
+ * @example
2894
+ * ```typescript
2895
+ * import { AttendancePolicySchema } from '@classytic/payroll';
2896
+ * import { model } from 'mongoose';
2897
+ *
2898
+ * const AttendancePolicy = model('AttendancePolicy', AttendancePolicySchema);
2899
+ *
2900
+ * // Create a new policy
2901
+ * const policy = new AttendancePolicy({
2902
+ * name: 'Tech Department Policy',
2903
+ * lateArrival: { ... },
2904
+ * earlyDeparture: { ... },
2905
+ * overtime: { ... },
2906
+ * });
2907
+ * await policy.save();
2908
+ * ```
2909
+ */
2910
+ declare const AttendancePolicySchema: Schema;
2911
+ /**
2912
+ * Instance methods interface
2913
+ */
2914
+ interface AttendancePolicyDocument {
2915
+ isCurrentlyActive(): boolean;
2916
+ }
2917
+ /**
2918
+ * Static methods interface
2919
+ */
2920
+ interface AttendancePolicyModel {
2921
+ findActiveForOrganization(organizationId: any, date?: Date): Promise<any>;
2922
+ }
2923
+
2924
+ export { ALLOWANCE_TYPE, AddAllowanceParams, AddDeductionParams, Allowance, AlreadyProcessedError, AnyDocument, type AttendancePolicy, AttendancePolicyBuilder, type AttendancePolicyDocument, type AttendancePolicyModel, AttendancePolicySchema, AttendancePolicySchemaDefinition, BankDetails, BulkPayrollResult, type CalculateShiftComplianceInput, type ClockRoundingPolicy, ClockRoundingPolicyBuilder, ClockRoundingPolicySchema, ClockRoundingPolicySchemaDefinition, Compensation, type CreateEmployeeParams, type CreatePayrollTransactionInput, type CreateTaxPaymentTransactionInput, DEDUCTION_TYPE, DEFAULT_ATTENDANCE_POLICY, DEPARTMENT, Deduction, DeepPartial, Department, DuplicatePayrollError, EMPLOYEE_STATUS, EMPLOYEE_TIMELINE_CONFIG, EMPLOYMENT_TYPE, type EarlyDeparturePenaltyResult, type EarlyDeparturePolicy, EarlyDeparturePolicySchema, EarlyDeparturePolicySchemaDefinition, type EarlyOccurrence, EmployeeBuilder, type EmployeeData, EmployeeDocument, EmployeeFactory, EmployeeIdentityMode, EmployeeNotFoundError, type EmployeePluginOptions, EmployeeStatusMachine, type EmployeeStatusState, EmployeeTerminatedError, EmploymentType, ErrorCode, ExportPayrollParams, GetPendingTaxParams, HEALTHCARE_POLICY, HOSPITALITY_POLICY, HRMConfig, HRM_CONFIG, HireEmployeeParams, type Holiday, HttpError, type IPayrollTransaction, type IPayrollTransactionCreateInput, IdempotencyManager, type IdempotentResult, InvalidEmployeeError, LEAVE_REQUEST_STATUS, LEAVE_REQUEST_TIMELINE_CONFIG, LEAVE_TYPE, type LateArrivalPolicy, LateArrivalPolicySchema, LateArrivalPolicySchemaDefinition, type LateOccurrence, type LatePenaltyResult, LatePolicyBuilder, LeaveInitConfig, LeaveRequestDocument, LeaveRequestStatus, LeaveRequestStatusMachine, type LeaveRequestStatusState, LeaveType, Logger, MANUFACTURING_POLICY, MarkTaxPaidParams, type MaxPenaltiesPerPeriod, MaxPenaltiesSchema, MaxPenaltiesSchemaDefinition, type NightShiftDifferential, NightShiftDifferentialSchema, NightShiftDifferentialSchemaDefinition, NotEligibleError, NotInitializedError, OFFICE_POLICY, ObjectIdLike, OperationContext, OrgRole, type OvertimeBonusResult, type OvertimeMode, type OvertimeOccurrence, type OvertimePolicy, OvertimePolicyBuilder, OvertimePolicySchema, OvertimePolicySchemaDefinition, PAYMENT_FREQUENCY, PAYROLL_EVENTS, PAYROLL_RECORD_TIMELINE_CONFIG, PAYROLL_STATUS, PaymentFrequency, Payroll, PayrollBreakdown, PayrollBuilder, PayrollError, PayrollHistoryParams, PayrollInitConfig, PayrollInstance, PayrollRecordDocument, PayrollStatus, PayrollStatusMachine, type PayrollStatusState, PayrollSummaryParams, PayrollSummaryResult, type PayrollTimelineEvent, type PenaltyMode, type PenaltyOverride, type PenaltyTier, PenaltyTierSchema, PenaltyTierSchemaDefinition, ProcessBulkPayrollParams, ProcessSalaryParams, ProcessSalaryResult, RETAIL_POLICY, ReHireEmployeeParams, RemoveAllowanceParams, RemoveDeductionParams, type ResetPeriod, RestorePayrollParams, RestorePayrollResult, ReversePayrollParams, ReversePayrollResult, type RoundingMode, SecurityError, type ShiftComplianceData, type ShiftComplianceResult, type ShiftDifferentialResult, SingleTenantConfig, StateMachine, type StateMachineConfig, type StateTransition, TAX_STATUS, TAX_STATUS_VALUES, TAX_TYPE, TAX_TYPE_VALUES, TERMINATION_REASON, TaxStatus, TaxStatusMachine, type TaxStatusState, TaxSummaryParams, TaxSummaryResult, TaxType, TaxWithholdingDocument, TerminateEmployeeParams, type TerminationData, TerminationReason, TieredPenaltyBuilder, TransactionFactory, type TransitionResult, UpdateBankDetailsParams, UpdateEmploymentParams, UpdateSalaryParams, ValidationError, VoidPayrollParams, VoidPayrollResult, WebhookConfig, WebhookDelivery, type WeekendPremium, WeekendPremiumSchema, WeekendPremiumSchemaDefinition, WorkSchedule, batchGetAttendance, buildRequestContext, buildTimelineMetadata, calculateDailyOvertime, calculateFlatPenalty, calculateLatePenalty, calculateMonthlyOvertime, calculateNightShiftDifferential, calculateOvertimeBonus, calculatePerMinutePenalty, calculatePercentagePenalty, calculateShiftCompliance, calculateTieredPenalty, calculateWeekendPremium, calculateWeeklyOvertime, createClockRoundingPolicyBuilder, createEmployee, createError, createHolidaySchema, createLatePolicyBuilder, createOvertimePolicyBuilder, createPayrollInstance, createPayrollTransaction, createPolicyFromPreset, createStateMachine, createTaxPaymentTransaction, determineOrgRole, employeePlugin, extractErrorInfo, generatePayrollIdempotencyKey, getAttendance, getHolidays, isApprovedLeaveStatus, isCancelledTaxStatus, isPaidLeaveType, isPaidTaxStatus, isPayrollError, isPayrollTransaction, isPendingLeaveStatus, isPendingTaxStatus, isValidLeaveRequestStatus, isValidLeaveType, isValidTaxStatus, isValidTaxType, isVoidablePayrollStatus, isVoidedOrReversedStatus, mergeConfig, multiTenantPlugin, requiresReversalPayrollStatus, toPayrollError };