@classytic/payroll 2.7.5 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,13 +1,15 @@
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';
1
+ import { E as EmployeeDocument, P as PayrollRecordDocument, A as AnyDocument, aq as PayrollInstance, ar as PayrollInitConfig, l as PayrollPluginDefinition, i as PayrollEventMap, W as WebhookConfig, j as PayrollEventType, v as WebhookDelivery, as as HireEmployeeParams, at as UpdateEmploymentParams, au as TerminateEmployeeParams, av as ReHireEmployeeParams, a2 as ObjectIdLike, ap as OperationContext, aw as EmployeeIdentityMode, ax as UpdateSalaryParams, ay as AddAllowanceParams, az as RemoveAllowanceParams, aA as AddDeductionParams, aB as RemoveDeductionParams, aC as UpdateBankDetailsParams, aD as ProcessSalaryParams, aE as ProcessSalaryResult, aF as ProcessBulkPayrollParams, aG as BulkPayrollResult, aH as PayrollHistoryParams, aI as PayrollSummaryParams, aJ as PayrollSummaryResult, aK as VoidPayrollParams, aL as VoidPayrollResult, aM as ReversePayrollParams, aN as ReversePayrollResult, aO as RestorePayrollParams, aP as RestorePayrollResult, aQ as GetPendingTaxParams, T as TaxWithholdingDocument, aR as TaxSummaryParams, aS as TaxSummaryResult, aT as MarkTaxPaidParams, a3 as ObjectId, aU as ExportPayrollParams, L as LeaveRequestDocument, aV as DeepPartial, H as HRMConfig, S as SingleTenantConfig, a as Logger, a1 as PayrollBreakdown, a6 as LeaveRequestStatus, a5 as TaxStatus, a7 as LeaveType, a4 as TaxType, ai as PayrollStatus, ah as Department, ag as EmploymentType, aW as OrgRole, ao as LeaveInitConfig, aX as WorkSchedule, aY as PaymentFrequency, a9 as Allowance, ab as Deduction, af as BankDetails, _ as Compensation, aZ as TerminationReason, b as AttendanceInput } from './types-bZdAJueH.js';
2
+ export { a_ as AccrueLeaveOptions, a$ as AllowanceType, b0 as AnyModel, b1 as BulkPayrollProgress, aa as CompensationBreakdownResult, b2 as DataRetentionConfig, b3 as DeductionType, b4 as EmployeeHiredEvent, b5 as EmployeeIdMode, b6 as EmployeeOperationParams, ad as EmployeeStatus, ae as EmployeeValidationResult, b7 as EmploymentConfig, b8 as EmploymentHistoryEntry, ak as ErrorCode, b9 as EventPayload, ba as EventPayloadBase, bb as FilterQuery, bc as GetEmployeeParams, bd as HRMTransactionCategory, aj as HttpError, al as LeaveBalance, be as LeaveHistoryFilters, an as LeaveSummaryResult, bf as Nullable, a8 as PayPeriodInfo, bg as PaymentMethod, bh as PayrollConfig, bi as PayrollCorrection, bj as PayrollEmployee, bk as PayrollEvent, bl as PayrollPeriod, bm as PayrollPlugin, bn as PayrollStats, n as PluginContext, bo as PluginFunction, o as PluginHooks, bp as PluginType, bq as PreTaxDeductionInput, br as QueryOptions, bs as RequestLeaveInput, bt as ResetAnnualLeaveOptions, bu as ReviewLeaveRequestInput, bv as RoleMappingConfig, bw as SalaryBand, bx as SalaryBandRange, by as SalaryConfig, bz as SalaryProcessedEvent, $ as TaxBracket, a0 as TaxCalculationOptions, ac as TaxCalculationResult, bA as TaxCreditInput, bB as TaxSummaryByType, bC as UserReference, bD as ValidationConfig, w as WebhookManager, bE as WithPayroll, am as WorkingDaysOptions, I as definePlugin } from './types-bZdAJueH.js';
3
3
  import * as mongoose from 'mongoose';
4
- import { ClientSession, Model, Schema, SchemaDefinition } from 'mongoose';
4
+ import { ClientSession, Model, Schema, Types, Document, SchemaDefinition } from 'mongoose';
5
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';
6
+ export { E as EMPLOYEE_TIMELINE_CONFIG, a as EmployeeStatusMachine, b as EmployeeStatusState, I as IdempotencyManager, c as IdempotentResult, L as LEAVE_REQUEST_TIMELINE_CONFIG, d as LeaveRequestStatusMachine, e as LeaveRequestStatusState, P as PAYROLL_EVENTS, f as PAYROLL_RECORD_TIMELINE_CONFIG, g as PayrollStatusMachine, h as PayrollStatusState, i as PayrollTimelineEvent, S as StateMachine, j as StateMachineConfig, k as StateTransition, T as TaxStatusMachine, l as TaxStatusState, m as TransitionResult, n as buildRequestContext, o as buildTimelineMetadata, p as createStateMachine, q as generatePayrollIdempotencyKey, r as multiTenantPlugin } from './payroll-states-DBt0XVm-.js';
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 employeeIndexes, n as employmentHistorySchema, o as getLeaveRequestFields, p as getLeaveRequestModel, q as getTaxWithholdingFields, r as getTaxWithholdingModel, s as leaveBalanceFields, t as leaveBalanceSchema, u as leaveRequestIndexes, v as leaveRequestSchema, w as payrollRecordIndexes, x as payrollStatsSchema, y as taxWithholdingIndexes, z as taxWithholdingSchema, A as workScheduleSchema } from './index-BKLkuSAs.js';
8
+ export { J as AlreadyProcessedError, C as ContainerLike, D as DEFAULT_CARRY_OVER, a as DEFAULT_LEAVE_ALLOCATIONS, b as DuplicateKeyErrorResult, K as DuplicatePayrollError, c as EmployeeIdType, L as EmployeeNotFoundError, d as EmployeeQueryFilter, M as EmployeeTerminatedError, N as InvalidEmployeeError, O as NotEligibleError, Q as NotInitializedError, U as PayrollError, P as PayrollErrorResult, R as ResolveOrganizationIdParams, S as SecureEmployeeLookupOptions, V as SecurityError, T as TransactionErrorResult, W as ValidationError, e as accrueLeaveToBalance, f as calculateCarryOver, g as calculateLeaveDays, h as calculateUnpaidLeaveDeduction, X as createError, i as detectEmployeeIdType, j as employeeExistsSecure, Y as extractErrorInfo, k as findEmployeeSecure, l as findEmployeesSecure, m as formatEmployeeId, n as formatUserError, o as getAvailableDays, p as getLeaveBalance, q as getLeaveBalances, r as getLeaveSummary, s as getUnpaidLeaveDays, t as handleDuplicateKeyError, u as handlePayrollError, v as handleTransactionError, w as hasLeaveBalance, x as initializeLeaveBalances, y as isObjectIdEmployeeId, Z as isPayrollError, z as isStringEmployeeId, A as normalizeEmployeeId, B as proRateAllocation, F as requireOrganizationId, G as resolveOrganizationId, $ as toPayrollError, H as tryResolveOrganizationId, I as validateOrganizationId } from './error-helpers-Bm6lMny2.js';
9
+ export { P as ProRatingInput, a as ProRatingResult, b as applyProRating, c as calculateProRating, s as shouldProRate } from './prorating.calculator-C33fWBQf.js';
10
+ export { A as AttendanceDeductionInput, a as AttendanceDeductionResult, P as ProcessedAllowance, b as ProcessedDeduction, S as SalaryCalculationInput, c as calculateAttendanceDeduction, d as calculateDailyRate, e as calculateHourlyRate, f as calculatePartialDayDeduction, g as calculateSalaryBreakdown, h as calculateTotalAttendanceDeduction } from './attendance.calculator-BZcv2iii.js';
11
+ import { MongoServerError } from 'mongodb';
12
+ import { Repository } from '@classytic/mongokit';
11
13
  import 'bson';
12
14
 
13
15
  /**
@@ -36,7 +38,6 @@ import 'bson';
36
38
  * ```
37
39
  */
38
40
  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
41
  private _container;
41
42
  private _events;
42
43
  private _plugins;
@@ -352,10 +353,6 @@ declare class Payroll<TEmployee extends EmployeeDocument = EmployeeDocument, TPa
352
353
  * Get payroll summary
353
354
  */
354
355
  payrollSummary(params: PayrollSummaryParams): Promise<PayrollSummaryResult>;
355
- /**
356
- * Export payroll data
357
- */
358
- exportPayroll(params: ExportPayrollParams): Promise<TPayrollRecord[]>;
359
356
  /**
360
357
  * Void a payroll record (before payment)
361
358
  *
@@ -421,7 +418,7 @@ declare class Payroll<TEmployee extends EmployeeDocument = EmployeeDocument, TPa
421
418
  */
422
419
  markTaxWithholdingsPaid(params: MarkTaxPaidParams): Promise<{
423
420
  withholdings: TaxWithholdingDocument[];
424
- transaction?: any;
421
+ transaction?: AnyDocument;
425
422
  }>;
426
423
  /**
427
424
  * Calculate salary breakdown
@@ -429,11 +426,92 @@ declare class Payroll<TEmployee extends EmployeeDocument = EmployeeDocument, TPa
429
426
  * Delegates to pure calculator for testability and reusability
430
427
  */
431
428
  private calculateSalaryBreakdown;
429
+ private updatePayrollStats;
432
430
  /**
433
- * Calculate attendance deduction using working days (not calendar days)
431
+ * Recover stuck payroll records
432
+ *
433
+ * Finds payroll records stuck in 'processing' or 'pending' status for longer
434
+ * than the threshold and handles them appropriately:
435
+ * - Records WITHOUT transactionId: Marked as 'failed' (safe to retry)
436
+ * - Records WITH transactionId: Flagged for manual review (orphaned transaction)
437
+ *
438
+ * This helps recover from server crashes or partial failures.
439
+ *
440
+ * @example
441
+ * ```typescript
442
+ * const recovered = await payroll.recoverStuckPayrolls({
443
+ * organizationId: org._id,
444
+ * staleThresholdMinutes: 30,
445
+ * });
446
+ * console.log(`Recovered ${recovered.markedFailed} records`);
447
+ * if (recovered.requiresManualReview.length > 0) {
448
+ * console.warn('Manual review needed:', recovered.requiresManualReview);
449
+ * }
450
+ * ```
434
451
  */
435
- private calculateAttendanceDeduction;
436
- private updatePayrollStats;
452
+ recoverStuckPayrolls(params: {
453
+ organizationId: ObjectIdLike;
454
+ staleThresholdMinutes?: number;
455
+ dryRun?: boolean;
456
+ }): Promise<{
457
+ markedFailed: number;
458
+ requiresManualReview: Array<{
459
+ _id: ObjectId;
460
+ status: string;
461
+ transactionId?: ObjectId;
462
+ }>;
463
+ scanned: number;
464
+ }>;
465
+ /**
466
+ * Prepare payroll data for export (Phase 1)
467
+ *
468
+ * Retrieves records but does NOT mark them as exported yet.
469
+ * Returns an exportId that must be used to confirm or cancel the export.
470
+ *
471
+ * @example
472
+ * ```typescript
473
+ * // Phase 1: Prepare
474
+ * const { records, exportId } = await payroll.prepareExport({
475
+ * organizationId: org._id,
476
+ * startDate: new Date('2024-01-01'),
477
+ * endDate: new Date('2024-01-31'),
478
+ * });
479
+ *
480
+ * // Send records to external system...
481
+ *
482
+ * // Phase 2: Confirm (if successful) or Cancel (if failed)
483
+ * await payroll.confirmExport({ organizationId: org._id, exportId });
484
+ * ```
485
+ */
486
+ prepareExport(params: ExportPayrollParams): Promise<{
487
+ records: TPayrollRecord[];
488
+ exportId: string;
489
+ total: number;
490
+ }>;
491
+ /**
492
+ * Confirm export success (Phase 2a)
493
+ *
494
+ * Marks records as exported after downstream system confirms receipt.
495
+ */
496
+ confirmExport(params: {
497
+ organizationId: ObjectIdLike;
498
+ exportId: string;
499
+ }): Promise<{
500
+ confirmed: number;
501
+ }>;
502
+ /**
503
+ * Cancel export (Phase 2b)
504
+ *
505
+ * Called when downstream system fails to process the export.
506
+ * Records remain unmarked and can be exported again.
507
+ */
508
+ cancelExport(params: {
509
+ organizationId: ObjectIdLike;
510
+ exportId: string;
511
+ reason?: string;
512
+ }): Promise<{
513
+ cancelled: boolean;
514
+ }>;
437
515
  /**
438
516
  * Create a new Payroll instance with default types
439
517
  */
@@ -642,537 +720,6 @@ declare class TransactionFactory {
642
720
  static createTaxPaymentTransaction: typeof createTaxPaymentTransaction;
643
721
  }
644
722
 
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
723
  declare const EMPLOYMENT_TYPE: {
1177
724
  readonly FULL_TIME: "full_time";
1178
725
  readonly PART_TIME: "part_time";
@@ -1536,111 +1083,6 @@ declare class EmployeeBuilder {
1536
1083
  */
1537
1084
  declare function createEmployee(): EmployeeBuilder;
1538
1085
 
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
1086
  /**
1645
1087
  * @classytic/payroll - Attendance Integration
1646
1088
  *
@@ -1714,7 +1156,7 @@ declare function batchGetAttendance(AttendanceModel: Model<unknown>, params: {
1714
1156
  * Holiday document
1715
1157
  */
1716
1158
  interface Holiday {
1717
- organizationId?: any;
1159
+ organizationId?: Types.ObjectId;
1718
1160
  date: Date;
1719
1161
  name: string;
1720
1162
  type: 'public' | 'company' | 'religious';
@@ -1749,8 +1191,8 @@ declare function createHolidaySchema(options?: {
1749
1191
  * });
1750
1192
  * ```
1751
1193
  */
1752
- declare function getHolidays(HolidayModel: Model<any>, params: {
1753
- organizationId?: any;
1194
+ declare function getHolidays(HolidayModel: Model<Holiday>, params: {
1195
+ organizationId?: Types.ObjectId;
1754
1196
  startDate: Date;
1755
1197
  endDate: Date;
1756
1198
  }): Promise<Date[]>;
@@ -2918,7 +2360,325 @@ interface AttendancePolicyDocument {
2918
2360
  * Static methods interface
2919
2361
  */
2920
2362
  interface AttendancePolicyModel {
2921
- findActiveForOrganization(organizationId: any, date?: Date): Promise<any>;
2363
+ findActiveForOrganization(organizationId: Types.ObjectId, date?: Date): Promise<Document | null>;
2364
+ }
2365
+
2366
+ /**
2367
+ * @classytic/payroll - Type Guards
2368
+ *
2369
+ * Type-safe utilities for runtime type checking,
2370
+ * especially for error handling and MongoDB errors.
2371
+ *
2372
+ * @module @classytic/payroll/utils/type-guards
2373
+ */
2374
+
2375
+ /**
2376
+ * Check if error is a MongoDB error
2377
+ *
2378
+ * @param error - Unknown error object
2379
+ * @returns True if MongoDB error
2380
+ *
2381
+ * @example
2382
+ * ```typescript
2383
+ * try {
2384
+ * await model.create(data);
2385
+ * } catch (error) {
2386
+ * if (isMongoError(error)) {
2387
+ * console.log('MongoDB error code:', error.code);
2388
+ * }
2389
+ * }
2390
+ * ```
2391
+ */
2392
+ declare function isMongoError(error: unknown): error is MongoServerError;
2393
+ /**
2394
+ * Check if error is a MongoDB duplicate key error (E11000)
2395
+ *
2396
+ * @param error - Unknown error object
2397
+ * @returns True if duplicate key error
2398
+ *
2399
+ * @example
2400
+ * ```typescript
2401
+ * try {
2402
+ * await PayrollModel.create(record);
2403
+ * } catch (error) {
2404
+ * if (isDuplicateKeyError(error)) {
2405
+ * const field = parseDuplicateKeyError(error);
2406
+ * throw new DuplicatePayrollError(`Duplicate ${field}`);
2407
+ * }
2408
+ * }
2409
+ * ```
2410
+ */
2411
+ declare function isDuplicateKeyError(error: unknown): error is MongoServerError & {
2412
+ code: 11000;
2413
+ };
2414
+ /**
2415
+ * Parse field name from MongoDB duplicate key error
2416
+ *
2417
+ * @param error - MongoDB duplicate key error
2418
+ * @returns Field name that caused the duplicate, or 'unknown'
2419
+ *
2420
+ * @example
2421
+ * ```typescript
2422
+ * if (isDuplicateKeyError(error)) {
2423
+ * const field = parseDuplicateKeyError(error);
2424
+ * // field might be 'employeeId', 'email', etc.
2425
+ * }
2426
+ * ```
2427
+ */
2428
+ declare function parseDuplicateKeyError(error: MongoServerError): string;
2429
+ /**
2430
+ * Check if error is a MongoDB transaction error
2431
+ *
2432
+ * @param error - Unknown error object
2433
+ * @returns True if transaction-related error
2434
+ */
2435
+ declare function isTransactionError(error: unknown): error is MongoServerError;
2436
+ /**
2437
+ * Check if MongoDB transactions are unsupported (standalone server)
2438
+ *
2439
+ * @param error - Unknown error object
2440
+ * @returns True if error indicates transactions are not supported
2441
+ */
2442
+ declare function isTransactionUnsupportedError(error: unknown): boolean;
2443
+ /**
2444
+ * Check if error is a connection error
2445
+ *
2446
+ * @param error - Unknown error object
2447
+ * @returns True if connection error
2448
+ */
2449
+ declare function isConnectionError(error: unknown): error is MongoServerError;
2450
+ /**
2451
+ * Type guard: Check if employee is a guest employee (no userId)
2452
+ *
2453
+ * @param employee - Employee document
2454
+ * @returns True if guest employee
2455
+ *
2456
+ * @example
2457
+ * ```typescript
2458
+ * if (isGuestEmployee(employee)) {
2459
+ * // Handle guest-specific logic
2460
+ * console.log('Guest employee:', employee.email);
2461
+ * }
2462
+ * ```
2463
+ */
2464
+ declare function isGuestEmployee(employee: EmployeeDocument): boolean;
2465
+ /**
2466
+ * Type guard: Check if employee has a user ID
2467
+ *
2468
+ * @param employee - Employee document
2469
+ * @returns True if employee has userId (not guest)
2470
+ */
2471
+ declare function hasUserId(employee: EmployeeDocument): employee is EmployeeDocument & {
2472
+ userId: NonNullable<EmployeeDocument['userId']>;
2473
+ };
2474
+ /**
2475
+ * Check if error is a validation error
2476
+ *
2477
+ * @param error - Unknown error object
2478
+ * @returns True if Mongoose/MongoDB validation error
2479
+ */
2480
+ declare function isValidationError(error: unknown): error is Error & {
2481
+ name: 'ValidationError';
2482
+ };
2483
+ /**
2484
+ * Type guard for Error instances
2485
+ *
2486
+ * @param error - Unknown value
2487
+ * @returns True if Error instance
2488
+ */
2489
+ declare function isError(error: unknown): error is Error;
2490
+ /**
2491
+ * Safe error message extraction
2492
+ *
2493
+ * @param error - Unknown error object
2494
+ * @returns Error message or generic fallback
2495
+ *
2496
+ * @example
2497
+ * ```typescript
2498
+ * try {
2499
+ * await dangerousOperation();
2500
+ * } catch (error) {
2501
+ * logger.error(getErrorMessage(error));
2502
+ * }
2503
+ * ```
2504
+ */
2505
+ declare function getErrorMessage(error: unknown): string;
2506
+
2507
+ /**
2508
+ * Safely get email from employee (guest or regular)
2509
+ *
2510
+ * @param employee - Employee document
2511
+ * @returns Email address or undefined
2512
+ *
2513
+ * @example
2514
+ * ```typescript
2515
+ * const email = getEmployeeEmail(employee);
2516
+ * if (email) {
2517
+ * sendNotification(email, 'Payroll processed');
2518
+ * }
2519
+ * ```
2520
+ */
2521
+ declare function getEmployeeEmail(employee: EmployeeDocument): string | undefined;
2522
+ /**
2523
+ * Get employee name (from userId if populated, fallback to employeeId)
2524
+ *
2525
+ * @param employee - Employee document
2526
+ * @returns Employee name or employee ID
2527
+ *
2528
+ * @example
2529
+ * ```typescript
2530
+ * const name = getEmployeeName(employee);
2531
+ * console.log(`Processing payroll for ${name}`);
2532
+ * ```
2533
+ */
2534
+ declare function getEmployeeName(employee: EmployeeDocument): string;
2535
+
2536
+ /**
2537
+ * @classytic/payroll - Payroll Audit Plugin
2538
+ *
2539
+ * Mongokit plugin for automatic audit trail capture on all payroll operations.
2540
+ * Auto-captures who/when/where for creates and updates.
2541
+ *
2542
+ * @module @classytic/payroll/core/mongokit-plugins/payroll-audit
2543
+ */
2544
+
2545
+ /**
2546
+ * Audit context configuration
2547
+ */
2548
+ interface AuditContext {
2549
+ /** User ID performing the operation */
2550
+ userId?: ObjectId;
2551
+ /** User name (optional, for logging) */
2552
+ userName?: string;
2553
+ /** Organization ID (for multi-tenant operations) */
2554
+ organizationId?: ObjectId;
2555
+ }
2556
+ /**
2557
+ * Payroll audit trail plugin
2558
+ *
2559
+ * Automatically captures audit information on create and update operations:
2560
+ * - Creates: Sets createdBy, createdAt, organizationId
2561
+ * - Updates: Sets updatedBy, updatedAt
2562
+ *
2563
+ * @param context - Audit context with user and organization info
2564
+ * @returns Mongokit plugin function
2565
+ *
2566
+ * @example
2567
+ * ```typescript
2568
+ * // Single-tenant mode with audit
2569
+ * const repos = {
2570
+ * payrollRecord: new Repository(PayrollRecordModel, [
2571
+ * payrollAuditPlugin({ userId: admin._id, organizationId: org._id }),
2572
+ * ]),
2573
+ * };
2574
+ *
2575
+ * // Create will automatically set createdBy and createdAt
2576
+ * const record = await repos.payrollRecord.create({
2577
+ * employeeId: emp._id,
2578
+ * // ... other fields
2579
+ * // createdBy and createdAt will be auto-added
2580
+ * });
2581
+ * ```
2582
+ *
2583
+ * @example
2584
+ * ```typescript
2585
+ * // Multi-tenant mode with audit and multi-tenant plugin
2586
+ * import { multiTenantPlugin } from '../repository-plugins.js';
2587
+ *
2588
+ * const repos = {
2589
+ * employee: new Repository(EmployeeModel, [
2590
+ * multiTenantPlugin(orgId), // First: enforce multi-tenancy
2591
+ * payrollAuditPlugin({ userId, organizationId: orgId }), // Second: audit trail
2592
+ * ]),
2593
+ * };
2594
+ * ```
2595
+ *
2596
+ * @example
2597
+ * ```typescript
2598
+ * // Per-request audit context
2599
+ * function createAuditedRepos(req: Request) {
2600
+ * const context = {
2601
+ * userId: req.user._id,
2602
+ * userName: req.user.name,
2603
+ * organizationId: req.organization._id,
2604
+ * };
2605
+ *
2606
+ * return {
2607
+ * payrollRecord: new Repository(PayrollRecordModel, [
2608
+ * payrollAuditPlugin(context),
2609
+ * ]),
2610
+ * };
2611
+ * }
2612
+ * ```
2613
+ */
2614
+ declare function payrollAuditPlugin(context: AuditContext): (repo: Repository) => void;
2615
+ /**
2616
+ * Read-only audit plugin (tracks access without modification)
2617
+ *
2618
+ * Logs who accessed what data, useful for compliance and security auditing.
2619
+ *
2620
+ * @param context - Audit context
2621
+ * @param logger - Optional logger function
2622
+ * @returns Mongokit plugin function
2623
+ *
2624
+ * @example
2625
+ * ```typescript
2626
+ * const repos = {
2627
+ * employee: new Repository(EmployeeModel, [
2628
+ * readAuditPlugin(
2629
+ * { userId: user._id, organizationId: org._id },
2630
+ * (event) => console.log('Access log:', event)
2631
+ * ),
2632
+ * ]),
2633
+ * };
2634
+ *
2635
+ * // This will log the access
2636
+ * await repos.employee.getById(employeeId);
2637
+ * ```
2638
+ */
2639
+ declare function readAuditPlugin(context: AuditContext, logger?: (event: AuditEvent) => void): (repo: Repository) => void;
2640
+ /**
2641
+ * Audit event structure
2642
+ */
2643
+ interface AuditEvent {
2644
+ /** Operation type */
2645
+ operation: 'create' | 'read' | 'update' | 'delete';
2646
+ /** Model name */
2647
+ model: string;
2648
+ /** User performing operation */
2649
+ userId?: ObjectId;
2650
+ /** Organization context */
2651
+ organizationId?: ObjectId;
2652
+ /** When the operation occurred */
2653
+ timestamp: Date;
2654
+ /** Query or data involved */
2655
+ query?: Record<string, unknown>;
2656
+ /** Additional metadata */
2657
+ metadata?: Record<string, unknown>;
2922
2658
  }
2659
+ /**
2660
+ * Full audit trail plugin (create/read/update/delete)
2661
+ *
2662
+ * Combines both modification and access audit trails.
2663
+ *
2664
+ * @param context - Audit context
2665
+ * @param onEvent - Event handler for all audit events
2666
+ * @returns Mongokit plugin function
2667
+ *
2668
+ * @example
2669
+ * ```typescript
2670
+ * const auditLog: AuditEvent[] = [];
2671
+ *
2672
+ * const repos = {
2673
+ * payrollRecord: new Repository(PayrollRecordModel, [
2674
+ * fullAuditPlugin(
2675
+ * { userId: admin._id, organizationId: org._id },
2676
+ * (event) => auditLog.push(event)
2677
+ * ),
2678
+ * ]),
2679
+ * };
2680
+ * ```
2681
+ */
2682
+ declare function fullAuditPlugin(context: AuditContext, onEvent: (event: AuditEvent) => void | Promise<void>): (repo: Repository) => void;
2923
2683
 
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 };
2684
+ export { ALLOWANCE_TYPE, AddAllowanceParams, AddDeductionParams, Allowance, AnyDocument, type AttendancePolicy, AttendancePolicyBuilder, type AttendancePolicyDocument, type AttendancePolicyModel, AttendancePolicySchema, AttendancePolicySchemaDefinition, type AuditContext, type AuditEvent, 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, EMPLOYEE_STATUS, EMPLOYMENT_TYPE, type EarlyDeparturePenaltyResult, type EarlyDeparturePolicy, EarlyDeparturePolicySchema, EarlyDeparturePolicySchemaDefinition, type EarlyOccurrence, EmployeeBuilder, type EmployeeData, EmployeeDocument, EmployeeFactory, EmployeeIdentityMode, type EmployeePluginOptions, EmploymentType, ExportPayrollParams, GetPendingTaxParams, HEALTHCARE_POLICY, HOSPITALITY_POLICY, HRMConfig, HRM_CONFIG, HireEmployeeParams, type Holiday, type IPayrollTransaction, type IPayrollTransactionCreateInput, LEAVE_REQUEST_STATUS, LEAVE_TYPE, type LateArrivalPolicy, LateArrivalPolicySchema, LateArrivalPolicySchemaDefinition, type LateOccurrence, type LatePenaltyResult, LatePolicyBuilder, LeaveInitConfig, LeaveRequestDocument, LeaveRequestStatus, LeaveType, Logger, MANUFACTURING_POLICY, MarkTaxPaidParams, type MaxPenaltiesPerPeriod, MaxPenaltiesSchema, MaxPenaltiesSchemaDefinition, type NightShiftDifferential, NightShiftDifferentialSchema, NightShiftDifferentialSchemaDefinition, OFFICE_POLICY, ObjectIdLike, OperationContext, OrgRole, type OvertimeBonusResult, type OvertimeMode, type OvertimeOccurrence, type OvertimePolicy, OvertimePolicyBuilder, OvertimePolicySchema, OvertimePolicySchemaDefinition, PAYMENT_FREQUENCY, PAYROLL_STATUS, PaymentFrequency, Payroll, PayrollBreakdown, PayrollBuilder, PayrollHistoryParams, PayrollInitConfig, PayrollInstance, PayrollPluginDefinition, PayrollRecordDocument, PayrollStatus, PayrollSummaryParams, PayrollSummaryResult, type PenaltyMode, type PenaltyOverride, type PenaltyTier, PenaltyTierSchema, PenaltyTierSchemaDefinition, ProcessBulkPayrollParams, ProcessSalaryParams, ProcessSalaryResult, RETAIL_POLICY, ReHireEmployeeParams, RemoveAllowanceParams, RemoveDeductionParams, type ResetPeriod, RestorePayrollParams, RestorePayrollResult, ReversePayrollParams, ReversePayrollResult, type RoundingMode, type ShiftComplianceData, type ShiftComplianceResult, type ShiftDifferentialResult, SingleTenantConfig, TAX_STATUS, TAX_STATUS_VALUES, TAX_TYPE, TAX_TYPE_VALUES, TERMINATION_REASON, TaxStatus, TaxSummaryParams, TaxSummaryResult, TaxType, TaxWithholdingDocument, TerminateEmployeeParams, type TerminationData, TerminationReason, TieredPenaltyBuilder, TransactionFactory, UpdateBankDetailsParams, UpdateEmploymentParams, UpdateSalaryParams, VoidPayrollParams, VoidPayrollResult, WebhookConfig, WebhookDelivery, type WeekendPremium, WeekendPremiumSchema, WeekendPremiumSchemaDefinition, WorkSchedule, batchGetAttendance, calculateDailyOvertime, calculateFlatPenalty, calculateLatePenalty, calculateMonthlyOvertime, calculateNightShiftDifferential, calculateOvertimeBonus, calculatePerMinutePenalty, calculatePercentagePenalty, calculateShiftCompliance, calculateTieredPenalty, calculateWeekendPremium, calculateWeeklyOvertime, createClockRoundingPolicyBuilder, createEmployee, createHolidaySchema, createLatePolicyBuilder, createOvertimePolicyBuilder, createPayrollInstance, createPayrollTransaction, createPolicyFromPreset, createTaxPaymentTransaction, determineOrgRole, employeePlugin, fullAuditPlugin, getAttendance, getEmployeeEmail, getEmployeeName, getErrorMessage, getHolidays, hasUserId, isApprovedLeaveStatus, isCancelledTaxStatus, isConnectionError, isDuplicateKeyError, isError, isGuestEmployee, isMongoError, isPaidLeaveType, isPaidTaxStatus, isPayrollTransaction, isPendingLeaveStatus, isPendingTaxStatus, isTransactionError, isTransactionUnsupportedError, isValidLeaveRequestStatus, isValidLeaveType, isValidTaxStatus, isValidTaxType, isValidationError, isVoidablePayrollStatus, isVoidedOrReversedStatus, mergeConfig, parseDuplicateKeyError, payrollAuditPlugin, readAuditPlugin, requiresReversalPayrollStatus };