@classytic/payroll 1.0.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of @classytic/payroll might be problematic. Click here for more details.
- package/README.md +168 -489
- package/dist/core/index.d.ts +480 -0
- package/dist/core/index.js +971 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index-CTjHlCzz.d.ts +721 -0
- package/dist/index.d.ts +967 -0
- package/dist/index.js +4352 -0
- package/dist/index.js.map +1 -0
- package/dist/payroll.d.ts +233 -0
- package/dist/payroll.js +2103 -0
- package/dist/payroll.js.map +1 -0
- package/dist/plugin-D9mOr3_d.d.ts +333 -0
- package/dist/schemas/index.d.ts +2869 -0
- package/dist/schemas/index.js +440 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.js +1696 -0
- package/dist/services/index.js.map +1 -0
- package/dist/types-BSYyX2KJ.d.ts +671 -0
- package/dist/utils/index.d.ts +873 -0
- package/dist/utils/index.js +1046 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +54 -37
- package/dist/types/config.d.ts +0 -162
- package/dist/types/core/compensation.manager.d.ts +0 -54
- package/dist/types/core/employment.manager.d.ts +0 -49
- package/dist/types/core/payroll.manager.d.ts +0 -60
- package/dist/types/enums.d.ts +0 -117
- package/dist/types/factories/compensation.factory.d.ts +0 -196
- package/dist/types/factories/employee.factory.d.ts +0 -149
- package/dist/types/factories/payroll.factory.d.ts +0 -319
- package/dist/types/hrm.orchestrator.d.ts +0 -47
- package/dist/types/index.d.ts +0 -20
- package/dist/types/init.d.ts +0 -30
- package/dist/types/models/payroll-record.model.d.ts +0 -3
- package/dist/types/plugins/employee.plugin.d.ts +0 -2
- package/dist/types/schemas/employment.schema.d.ts +0 -959
- package/dist/types/services/compensation.service.d.ts +0 -94
- package/dist/types/services/employee.service.d.ts +0 -28
- package/dist/types/services/payroll.service.d.ts +0 -30
- package/dist/types/utils/calculation.utils.d.ts +0 -26
- package/dist/types/utils/date.utils.d.ts +0 -35
- package/dist/types/utils/logger.d.ts +0 -12
- package/dist/types/utils/query-builders.d.ts +0 -83
- package/dist/types/utils/validation.utils.d.ts +0 -33
- package/payroll.d.ts +0 -241
- package/src/config.js +0 -177
- package/src/core/compensation.manager.js +0 -242
- package/src/core/employment.manager.js +0 -224
- package/src/core/payroll.manager.js +0 -499
- package/src/enums.js +0 -141
- package/src/factories/compensation.factory.js +0 -198
- package/src/factories/employee.factory.js +0 -173
- package/src/factories/payroll.factory.js +0 -413
- package/src/hrm.orchestrator.js +0 -139
- package/src/index.js +0 -172
- package/src/init.js +0 -62
- package/src/models/payroll-record.model.js +0 -126
- package/src/plugins/employee.plugin.js +0 -164
- package/src/schemas/employment.schema.js +0 -126
- package/src/services/compensation.service.js +0 -231
- package/src/services/employee.service.js +0 -162
- package/src/services/payroll.service.js +0 -213
- package/src/utils/calculation.utils.js +0 -91
- package/src/utils/date.utils.js +0 -120
- package/src/utils/logger.js +0 -36
- package/src/utils/query-builders.js +0 -185
- package/src/utils/validation.utils.js +0 -122
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/logger.ts","../src/config.ts","../src/core/container.ts","../src/core/events.ts","../src/core/plugin.ts","../src/utils/date.ts","../src/factories/employee.factory.ts","../src/enums.ts","../src/utils/query-builders.ts","../src/utils/calculation.ts","../src/errors/index.ts","../src/payroll.ts","../src/schemas/index.ts","../src/models/payroll-record.model.ts","../src/utils/validation.ts","../src/factories/compensation.factory.ts","../src/plugins/employee.plugin.ts","../src/core/result.ts","../src/factories/payroll.factory.ts","../src/services/employee.service.ts","../src/services/payroll.service.ts","../src/services/compensation.service.ts","../src/attendance.ts","../src/holidays.ts","../src/index.ts"],"names":["logger","min","max","config","employee","mongoose","sum","payroll","Schema","periodSchema","match","minValue","maxValue","map"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * @classytic/payroll - Logger\r\n *\r\n * Pluggable logger abstraction\r\n * Defaults to console, can be replaced with pino, winston, etc.\r\n */\r\n\r\nimport type { Logger } from '../types.js';\r\n\r\n// ============================================================================\r\n// Default Logger Implementation\r\n// ============================================================================\r\n\r\nconst createConsoleLogger = (): Logger => ({\r\n info: (message: string, meta?: Record<string, unknown>) => {\r\n if (meta) {\r\n console.log(`[Payroll] INFO: ${message}`, meta);\r\n } else {\r\n console.log(`[Payroll] INFO: ${message}`);\r\n }\r\n },\r\n error: (message: string, meta?: Record<string, unknown>) => {\r\n if (meta) {\r\n console.error(`[Payroll] ERROR: ${message}`, meta);\r\n } else {\r\n console.error(`[Payroll] ERROR: ${message}`);\r\n }\r\n },\r\n warn: (message: string, meta?: Record<string, unknown>) => {\r\n if (meta) {\r\n console.warn(`[Payroll] WARN: ${message}`, meta);\r\n } else {\r\n console.warn(`[Payroll] WARN: ${message}`);\r\n }\r\n },\r\n debug: (message: string, meta?: Record<string, unknown>) => {\r\n if (process.env.NODE_ENV !== 'production') {\r\n if (meta) {\r\n console.log(`[Payroll] DEBUG: ${message}`, meta);\r\n } else {\r\n console.log(`[Payroll] DEBUG: ${message}`);\r\n }\r\n }\r\n },\r\n});\r\n\r\n// ============================================================================\r\n// Logger State\r\n// ============================================================================\r\n\r\nlet currentLogger: Logger = createConsoleLogger();\r\nlet loggingEnabled = true;\r\n\r\n// ============================================================================\r\n// Logger Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Get the current logger instance\r\n */\r\nexport function getLogger(): Logger {\r\n return currentLogger;\r\n}\r\n\r\n/**\r\n * Set a custom logger instance\r\n */\r\nexport function setLogger(logger: Logger): void {\r\n currentLogger = logger;\r\n}\r\n\r\n/**\r\n * Reset to default console logger\r\n */\r\nexport function resetLogger(): void {\r\n currentLogger = createConsoleLogger();\r\n}\r\n\r\n/**\r\n * Create a child logger with prefix\r\n */\r\nexport function createChildLogger(prefix: string): Logger {\r\n const parent = currentLogger;\r\n return {\r\n info: (message: string, meta?: Record<string, unknown>) =>\r\n parent.info(`[${prefix}] ${message}`, meta),\r\n error: (message: string, meta?: Record<string, unknown>) =>\r\n parent.error(`[${prefix}] ${message}`, meta),\r\n warn: (message: string, meta?: Record<string, unknown>) =>\r\n parent.warn(`[${prefix}] ${message}`, meta),\r\n debug: (message: string, meta?: Record<string, unknown>) =>\r\n parent.debug(`[${prefix}] ${message}`, meta),\r\n };\r\n}\r\n\r\n/**\r\n * Create a silent logger (for testing)\r\n */\r\nexport function createSilentLogger(): Logger {\r\n return {\r\n info: () => {},\r\n error: () => {},\r\n warn: () => {},\r\n debug: () => {},\r\n };\r\n}\r\n\r\n/**\r\n * Enable logging globally\r\n */\r\nexport function enableLogging(): void {\r\n loggingEnabled = true;\r\n}\r\n\r\n/**\r\n * Disable logging globally (useful for production)\r\n */\r\nexport function disableLogging(): void {\r\n loggingEnabled = false;\r\n}\r\n\r\n/**\r\n * Check if logging is enabled\r\n */\r\nexport function isLoggingEnabled(): boolean {\r\n return loggingEnabled;\r\n}\r\n\r\n// ============================================================================\r\n// Logger Proxy Object\r\n// ============================================================================\r\n\r\n/**\r\n * Logger proxy that always delegates to currentLogger\r\n * Respects global logging enabled/disabled state\r\n */\r\nexport const logger: Logger = {\r\n info: (message: string, meta?: Record<string, unknown>) => {\r\n if (loggingEnabled) currentLogger.info(message, meta);\r\n },\r\n error: (message: string, meta?: Record<string, unknown>) => {\r\n if (loggingEnabled) currentLogger.error(message, meta);\r\n },\r\n warn: (message: string, meta?: Record<string, unknown>) => {\r\n if (loggingEnabled) currentLogger.warn(message, meta);\r\n },\r\n debug: (message: string, meta?: Record<string, unknown>) => {\r\n if (loggingEnabled) currentLogger.debug(message, meta);\r\n },\r\n};\r\n\r\nexport default logger;\r\n\r\n","/**\r\n * @classytic/payroll - Configuration\r\n *\r\n * Centralized configuration with type safety\r\n * Configurable defaults for different use cases\r\n */\r\n\r\nimport type {\r\n HRMConfig,\r\n TaxBracket,\r\n SalaryBandRange,\r\n RoleMappingConfig,\r\n OrgRole,\r\n SalaryBand,\r\n Department,\r\n EmploymentType,\r\n PaymentFrequency,\r\n DeepPartial,\r\n} from './types.js';\r\n\r\n// ============================================================================\r\n// Default Configuration\r\n// ============================================================================\r\n\r\nexport const HRM_CONFIG: HRMConfig = {\r\n dataRetention: {\r\n payrollRecordsTTL: 63072000, // 2 years in seconds\r\n exportWarningDays: 30,\r\n archiveBeforeDeletion: true,\r\n },\r\n\r\n payroll: {\r\n defaultCurrency: 'BDT',\r\n allowProRating: true,\r\n attendanceIntegration: true,\r\n autoDeductions: true,\r\n overtimeEnabled: false,\r\n overtimeMultiplier: 1.5,\r\n },\r\n\r\n salary: {\r\n minimumWage: 0,\r\n maximumAllowances: 10,\r\n maximumDeductions: 10,\r\n defaultFrequency: 'monthly',\r\n },\r\n\r\n employment: {\r\n defaultProbationMonths: 3,\r\n maxProbationMonths: 6,\r\n allowReHiring: true,\r\n trackEmploymentHistory: true,\r\n },\r\n\r\n validation: {\r\n requireBankDetails: false,\r\n requireEmployeeId: true,\r\n uniqueEmployeeIdPerOrg: true,\r\n allowMultiTenantEmployees: true,\r\n },\r\n};\r\n\r\n// ============================================================================\r\n// Salary Bands Configuration\r\n// ============================================================================\r\n\r\nexport const SALARY_BANDS: Record<Exclude<SalaryBand, 'custom'>, SalaryBandRange> = {\r\n intern: { min: 10000, max: 20000 },\r\n junior: { min: 20000, max: 40000 },\r\n mid: { min: 40000, max: 70000 },\r\n senior: { min: 70000, max: 120000 },\r\n lead: { min: 100000, max: 200000 },\r\n executive: { min: 150000, max: 500000 },\r\n};\r\n\r\n// ============================================================================\r\n// Tax Brackets Configuration\r\n// ============================================================================\r\n\r\nexport const TAX_BRACKETS: Record<string, TaxBracket[]> = {\r\n BDT: [\r\n { min: 0, max: 300000, rate: 0 },\r\n { min: 300000, max: 400000, rate: 0.05 },\r\n { min: 400000, max: 500000, rate: 0.10 },\r\n { min: 500000, max: 600000, rate: 0.15 },\r\n { min: 600000, max: 3000000, rate: 0.20 },\r\n { min: 3000000, max: Infinity, rate: 0.25 },\r\n ],\r\n USD: [\r\n { min: 0, max: 10000, rate: 0.10 },\r\n { min: 10000, max: 40000, rate: 0.12 },\r\n { min: 40000, max: 85000, rate: 0.22 },\r\n { min: 85000, max: 165000, rate: 0.24 },\r\n { min: 165000, max: 215000, rate: 0.32 },\r\n { min: 215000, max: 540000, rate: 0.35 },\r\n { min: 540000, max: Infinity, rate: 0.37 },\r\n ],\r\n};\r\n\r\n// ============================================================================\r\n// Organization Roles Configuration\r\n// ============================================================================\r\n\r\nexport interface OrgRoleDefinition {\r\n key: OrgRole;\r\n label: string;\r\n description: string;\r\n}\r\n\r\nexport const ORG_ROLES: Record<Uppercase<OrgRole>, OrgRoleDefinition> = {\r\n OWNER: {\r\n key: 'owner',\r\n label: 'Owner',\r\n description: 'Full organization access (set by Organization model)',\r\n },\r\n MANAGER: {\r\n key: 'manager',\r\n label: 'Manager',\r\n description: 'Management and administrative features',\r\n },\r\n TRAINER: {\r\n key: 'trainer',\r\n label: 'Trainer',\r\n description: 'Training and coaching features',\r\n },\r\n STAFF: {\r\n key: 'staff',\r\n label: 'Staff',\r\n description: 'General staff access to basic features',\r\n },\r\n INTERN: {\r\n key: 'intern',\r\n label: 'Intern',\r\n description: 'Limited access for interns',\r\n },\r\n CONSULTANT: {\r\n key: 'consultant',\r\n label: 'Consultant',\r\n description: 'Project-based consultant access',\r\n },\r\n};\r\n\r\nexport const ORG_ROLE_KEYS = Object.values(ORG_ROLES).map((role) => role.key);\r\n\r\n// ============================================================================\r\n// Role Mapping Configuration\r\n// ============================================================================\r\n\r\nexport const ROLE_MAPPING: RoleMappingConfig = {\r\n byDepartment: {\r\n management: 'manager',\r\n training: 'trainer',\r\n sales: 'staff',\r\n operations: 'staff',\r\n finance: 'staff',\r\n hr: 'staff',\r\n marketing: 'staff',\r\n it: 'staff',\r\n support: 'staff',\r\n maintenance: 'staff',\r\n },\r\n\r\n byEmploymentType: {\r\n full_time: 'staff',\r\n part_time: 'staff',\r\n contract: 'consultant',\r\n intern: 'intern',\r\n consultant: 'consultant',\r\n },\r\n\r\n default: 'staff',\r\n};\r\n\r\n// ============================================================================\r\n// Configuration Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Calculate tax based on annual income\r\n */\r\nexport function calculateTax(annualIncome: number, currency = 'BDT'): number {\r\n const brackets = TAX_BRACKETS[currency];\r\n if (!brackets) return 0;\r\n\r\n let tax = 0;\r\n for (const bracket of brackets) {\r\n if (annualIncome > bracket.min) {\r\n const taxableAmount = Math.min(annualIncome, bracket.max) - bracket.min;\r\n tax += taxableAmount * bracket.rate;\r\n }\r\n }\r\n return Math.round(tax);\r\n}\r\n\r\n/**\r\n * Get salary band for a given amount\r\n */\r\nexport function getSalaryBand(amount: number): SalaryBand {\r\n for (const [band, range] of Object.entries(SALARY_BANDS)) {\r\n if (amount >= range.min && amount <= range.max) {\r\n return band as SalaryBand;\r\n }\r\n }\r\n return 'custom';\r\n}\r\n\r\n/**\r\n * Determine the appropriate organization role for an employee\r\n */\r\nexport function determineOrgRole(employmentData: {\r\n department?: Department | string;\r\n type?: EmploymentType | string;\r\n position?: string;\r\n}): OrgRole {\r\n const { department, type: employmentType } = employmentData;\r\n\r\n // Priority 1: Department-based mapping\r\n if (department && department in ROLE_MAPPING.byDepartment) {\r\n return ROLE_MAPPING.byDepartment[department as keyof typeof ROLE_MAPPING.byDepartment];\r\n }\r\n\r\n // Priority 2: Employment type mapping\r\n if (employmentType && employmentType in ROLE_MAPPING.byEmploymentType) {\r\n return ROLE_MAPPING.byEmploymentType[employmentType as keyof typeof ROLE_MAPPING.byEmploymentType];\r\n }\r\n\r\n // Priority 3: Default role\r\n return ROLE_MAPPING.default;\r\n}\r\n\r\n/**\r\n * Get pay periods per year based on frequency\r\n */\r\nexport function getPayPeriodsPerYear(frequency: PaymentFrequency): number {\r\n const periodsMap: Record<PaymentFrequency, number> = {\r\n monthly: 12,\r\n bi_weekly: 26,\r\n weekly: 52,\r\n daily: 365,\r\n hourly: 2080, // Assuming 40 hours/week * 52 weeks\r\n };\r\n return periodsMap[frequency];\r\n}\r\n\r\n/**\r\n * Calculate monthly equivalent from any frequency\r\n */\r\nexport function toMonthlyAmount(amount: number, frequency: PaymentFrequency): number {\r\n const periodsPerYear = getPayPeriodsPerYear(frequency);\r\n return Math.round((amount * periodsPerYear) / 12);\r\n}\r\n\r\n/**\r\n * Calculate annual equivalent from any frequency\r\n */\r\nexport function toAnnualAmount(amount: number, frequency: PaymentFrequency): number {\r\n const periodsPerYear = getPayPeriodsPerYear(frequency);\r\n return Math.round(amount * periodsPerYear);\r\n}\r\n\r\n/**\r\n * Merge configuration with defaults\r\n */\r\nexport function mergeConfig(\r\n customConfig: Partial<HRMConfig> | DeepPartial<HRMConfig> | undefined\r\n): HRMConfig {\r\n if (!customConfig) return HRM_CONFIG;\r\n\r\n return {\r\n dataRetention: { ...HRM_CONFIG.dataRetention, ...customConfig.dataRetention },\r\n payroll: { ...HRM_CONFIG.payroll, ...customConfig.payroll },\r\n salary: { ...HRM_CONFIG.salary, ...customConfig.salary },\r\n employment: { ...HRM_CONFIG.employment, ...customConfig.employment },\r\n validation: { ...HRM_CONFIG.validation, ...customConfig.validation },\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Default Export\r\n// ============================================================================\r\n\r\nexport default {\r\n HRM_CONFIG,\r\n SALARY_BANDS,\r\n TAX_BRACKETS,\r\n ORG_ROLES,\r\n ORG_ROLE_KEYS,\r\n ROLE_MAPPING,\r\n calculateTax,\r\n getSalaryBand,\r\n determineOrgRole,\r\n getPayPeriodsPerYear,\r\n toMonthlyAmount,\r\n toAnnualAmount,\r\n mergeConfig,\r\n};\r\n\r\n","/**\r\n * @classytic/payroll - Dependency Container\r\n *\r\n * Simple dependency injection container for service management\r\n * Enables clean dependency injection and testing\r\n */\r\n\r\nimport type { Model, ClientSession } from 'mongoose';\r\nimport type { Logger, HRMConfig, SingleTenantConfig } from '../types.js';\r\nimport { getLogger } from '../utils/logger.js';\r\nimport { HRM_CONFIG, mergeConfig } from '../config.js';\r\n\r\n// ============================================================================\r\n// Container Types\r\n// ============================================================================\r\n\r\nexport interface ModelsContainer {\r\n EmployeeModel: Model<any>;\r\n PayrollRecordModel: Model<any>;\r\n TransactionModel: Model<any>;\r\n AttendanceModel?: Model<any> | null;\r\n}\r\n\r\nexport interface ContainerConfig {\r\n models: ModelsContainer;\r\n config?: Partial<HRMConfig>;\r\n singleTenant?: SingleTenantConfig | null;\r\n logger?: Logger;\r\n}\r\n\r\n// ============================================================================\r\n// Container Class\r\n// ============================================================================\r\n\r\nexport class Container {\r\n private static instance: Container | null = null;\r\n \r\n private _models: ModelsContainer | null = null;\r\n private _config: HRMConfig = HRM_CONFIG;\r\n private _singleTenant: SingleTenantConfig | null = null;\r\n private _logger: Logger;\r\n private _initialized = false;\r\n\r\n private constructor() {\r\n this._logger = getLogger();\r\n }\r\n\r\n /**\r\n * Get singleton instance\r\n */\r\n static getInstance(): Container {\r\n if (!Container.instance) {\r\n Container.instance = new Container();\r\n }\r\n return Container.instance;\r\n }\r\n\r\n /**\r\n * Reset instance (for testing)\r\n */\r\n static resetInstance(): void {\r\n Container.instance = null;\r\n }\r\n\r\n /**\r\n * Initialize container with configuration\r\n */\r\n initialize(config: ContainerConfig): void {\r\n if (this._initialized) {\r\n this._logger.warn('Container already initialized, re-initializing');\r\n }\r\n\r\n this._models = config.models;\r\n this._config = mergeConfig(config.config);\r\n this._singleTenant = config.singleTenant ?? null;\r\n \r\n if (config.logger) {\r\n this._logger = config.logger;\r\n }\r\n\r\n this._initialized = true;\r\n\r\n this._logger.info('Container initialized', {\r\n hasEmployeeModel: !!this._models.EmployeeModel,\r\n hasPayrollRecordModel: !!this._models.PayrollRecordModel,\r\n hasTransactionModel: !!this._models.TransactionModel,\r\n hasAttendanceModel: !!this._models.AttendanceModel,\r\n isSingleTenant: !!this._singleTenant,\r\n });\r\n }\r\n\r\n /**\r\n * Check if container is initialized\r\n */\r\n isInitialized(): boolean {\r\n return this._initialized;\r\n }\r\n\r\n /**\r\n * Ensure container is initialized\r\n */\r\n private ensureInitialized(): void {\r\n if (!this._initialized || !this._models) {\r\n throw new Error(\r\n 'Payroll not initialized. Call Payroll.initialize() first.'\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Get models container\r\n */\r\n getModels(): ModelsContainer {\r\n this.ensureInitialized();\r\n return this._models!;\r\n }\r\n\r\n /**\r\n * Get Employee model\r\n */\r\n getEmployeeModel(): Model<any> {\r\n this.ensureInitialized();\r\n return this._models!.EmployeeModel;\r\n }\r\n\r\n /**\r\n * Get PayrollRecord model\r\n */\r\n getPayrollRecordModel(): Model<any> {\r\n this.ensureInitialized();\r\n return this._models!.PayrollRecordModel;\r\n }\r\n\r\n /**\r\n * Get Transaction model\r\n */\r\n getTransactionModel(): Model<any> {\r\n this.ensureInitialized();\r\n return this._models!.TransactionModel;\r\n }\r\n\r\n /**\r\n * Get Attendance model (optional)\r\n */\r\n getAttendanceModel(): Model<any> | null {\r\n this.ensureInitialized();\r\n return this._models!.AttendanceModel ?? null;\r\n }\r\n\r\n /**\r\n * Get configuration\r\n */\r\n getConfig(): HRMConfig {\r\n return this._config;\r\n }\r\n\r\n /**\r\n * Get specific config section\r\n */\r\n getConfigSection<K extends keyof HRMConfig>(section: K): HRMConfig[K] {\r\n return this._config[section];\r\n }\r\n\r\n /**\r\n * Check if single-tenant mode\r\n */\r\n isSingleTenant(): boolean {\r\n return !!this._singleTenant;\r\n }\r\n\r\n /**\r\n * Get single-tenant config\r\n */\r\n getSingleTenantConfig(): SingleTenantConfig | null {\r\n return this._singleTenant;\r\n }\r\n\r\n /**\r\n * Get organization ID (for single-tenant mode)\r\n */\r\n getOrganizationId(): string | null {\r\n if (!this._singleTenant || !this._singleTenant.organizationId) return null;\r\n return typeof this._singleTenant.organizationId === 'string'\r\n ? this._singleTenant.organizationId\r\n : this._singleTenant.organizationId.toString();\r\n }\r\n\r\n /**\r\n * Get logger\r\n */\r\n getLogger(): Logger {\r\n return this._logger;\r\n }\r\n\r\n /**\r\n * Set logger\r\n */\r\n setLogger(logger: Logger): void {\r\n this._logger = logger;\r\n }\r\n\r\n /**\r\n * Has attendance integration\r\n */\r\n hasAttendanceIntegration(): boolean {\r\n return (\r\n !!this._models?.AttendanceModel &&\r\n this._config.payroll.attendanceIntegration\r\n );\r\n }\r\n\r\n /**\r\n * Create operation context with defaults\r\n */\r\n createOperationContext(\r\n overrides?: Partial<{\r\n userId: string;\r\n userName: string;\r\n userRole: string;\r\n organizationId: string;\r\n session: ClientSession;\r\n }>\r\n ): {\r\n userId?: string;\r\n userName?: string;\r\n userRole?: string;\r\n organizationId?: string;\r\n session?: ClientSession;\r\n } {\r\n const context: Record<string, unknown> = {};\r\n\r\n // Auto-inject organizationId in single-tenant mode\r\n if (this._singleTenant?.autoInject && !overrides?.organizationId) {\r\n context.organizationId = this.getOrganizationId();\r\n }\r\n\r\n return { ...context, ...overrides };\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Convenience Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Get container instance\r\n */\r\nexport function getContainer(): Container {\r\n return Container.getInstance();\r\n}\r\n\r\n/**\r\n * Initialize container\r\n */\r\nexport function initializeContainer(config: ContainerConfig): void {\r\n Container.getInstance().initialize(config);\r\n}\r\n\r\n/**\r\n * Check if container is initialized\r\n */\r\nexport function isContainerInitialized(): boolean {\r\n return Container.getInstance().isInitialized();\r\n}\r\n\r\n/**\r\n * Get models from container\r\n */\r\nexport function getModels(): ModelsContainer {\r\n return Container.getInstance().getModels();\r\n}\r\n\r\n/**\r\n * Get config from container\r\n */\r\nexport function getConfig(): HRMConfig {\r\n return Container.getInstance().getConfig();\r\n}\r\n\r\n/**\r\n * Check if single-tenant mode\r\n */\r\nexport function isSingleTenant(): boolean {\r\n return Container.getInstance().isSingleTenant();\r\n}\r\n\r\n","/**\r\n * @classytic/payroll - Event System\r\n *\r\n * Type-safe event emitter for payroll lifecycle events\r\n * Enables loose coupling and extensibility\r\n */\r\n\r\nimport type {\r\n PayrollEvent,\r\n EmployeeDocument,\r\n PayrollRecordDocument,\r\n ObjectId,\r\n OperationContext,\r\n} from '../types.js';\r\n\r\n// ============================================================================\r\n// Event Payload Types\r\n// ============================================================================\r\n\r\nexport interface EmployeeHiredEventPayload {\r\n employee: {\r\n id: ObjectId;\r\n employeeId: string;\r\n position: string;\r\n department?: string;\r\n };\r\n organizationId: ObjectId;\r\n context?: OperationContext;\r\n}\r\n\r\nexport interface EmployeeTerminatedEventPayload {\r\n employee: {\r\n id: ObjectId;\r\n employeeId: string;\r\n name?: string;\r\n };\r\n terminationDate: Date;\r\n reason?: string;\r\n organizationId: ObjectId;\r\n context?: OperationContext;\r\n}\r\n\r\nexport interface EmployeeRehiredEventPayload {\r\n employee: {\r\n id: ObjectId;\r\n employeeId: string;\r\n position: string;\r\n };\r\n previousTerminationDate?: Date;\r\n organizationId: ObjectId;\r\n context?: OperationContext;\r\n}\r\n\r\nexport interface SalaryUpdatedEventPayload {\r\n employee: {\r\n id: ObjectId;\r\n employeeId: string;\r\n };\r\n previousSalary: number;\r\n newSalary: number;\r\n effectiveFrom: Date;\r\n organizationId: ObjectId;\r\n context?: OperationContext;\r\n}\r\n\r\nexport interface SalaryProcessedEventPayload {\r\n employee: {\r\n id: ObjectId;\r\n employeeId: string;\r\n name?: string;\r\n };\r\n payroll: {\r\n id: ObjectId;\r\n period: { month: number; year: number };\r\n grossAmount: number;\r\n netAmount: number;\r\n };\r\n transactionId: ObjectId;\r\n organizationId: ObjectId;\r\n context?: OperationContext;\r\n}\r\n\r\nexport interface SalaryFailedEventPayload {\r\n employee: {\r\n id: ObjectId;\r\n employeeId: string;\r\n };\r\n period: { month: number; year: number };\r\n error: string;\r\n organizationId: ObjectId;\r\n context?: OperationContext;\r\n}\r\n\r\nexport interface PayrollCompletedEventPayload {\r\n organizationId: ObjectId;\r\n period: { month: number; year: number };\r\n summary: {\r\n total: number;\r\n successful: number;\r\n failed: number;\r\n totalAmount: number;\r\n };\r\n context?: OperationContext;\r\n}\r\n\r\nexport interface PayrollExportedEventPayload {\r\n organizationId: ObjectId;\r\n dateRange: { start: Date; end: Date };\r\n recordCount: number;\r\n format: string;\r\n context?: OperationContext;\r\n}\r\n\r\nexport interface CompensationChangedEventPayload {\r\n employee: {\r\n id: ObjectId;\r\n employeeId: string;\r\n };\r\n changeType: 'allowance_added' | 'allowance_removed' | 'deduction_added' | 'deduction_removed';\r\n details: {\r\n type: string;\r\n amount: number;\r\n };\r\n organizationId: ObjectId;\r\n context?: OperationContext;\r\n}\r\n\r\nexport interface MilestoneAchievedEventPayload {\r\n employee: {\r\n id: ObjectId;\r\n employeeId: string;\r\n name?: string;\r\n };\r\n milestone: {\r\n type: 'tenure' | 'salary' | 'payments';\r\n value: number;\r\n message: string;\r\n };\r\n organizationId: ObjectId;\r\n}\r\n\r\n// ============================================================================\r\n// Event Map\r\n// ============================================================================\r\n\r\nexport interface PayrollEventMap {\r\n 'employee:hired': EmployeeHiredEventPayload;\r\n 'employee:terminated': EmployeeTerminatedEventPayload;\r\n 'employee:rehired': EmployeeRehiredEventPayload;\r\n 'salary:updated': SalaryUpdatedEventPayload;\r\n 'salary:processed': SalaryProcessedEventPayload;\r\n 'salary:failed': SalaryFailedEventPayload;\r\n 'payroll:completed': PayrollCompletedEventPayload;\r\n 'payroll:exported': PayrollExportedEventPayload;\r\n 'compensation:changed': CompensationChangedEventPayload;\r\n 'milestone:achieved': MilestoneAchievedEventPayload;\r\n}\r\n\r\nexport type PayrollEventType = keyof PayrollEventMap;\r\n\r\n// ============================================================================\r\n// Event Handler Types\r\n// ============================================================================\r\n\r\nexport type EventHandler<T> = (payload: T) => void | Promise<void>;\r\n\r\nexport type PayrollEventHandler<K extends PayrollEventType> = EventHandler<\r\n PayrollEventMap[K]\r\n>;\r\n\r\n// ============================================================================\r\n// EventBus Class\r\n// ============================================================================\r\n\r\nexport class EventBus {\r\n private handlers = new Map<\r\n PayrollEventType,\r\n Set<EventHandler<unknown>>\r\n >();\r\n\r\n /**\r\n * Register an event handler\r\n */\r\n on<K extends PayrollEventType>(\r\n event: K,\r\n handler: PayrollEventHandler<K>\r\n ): () => void {\r\n if (!this.handlers.has(event)) {\r\n this.handlers.set(event, new Set());\r\n }\r\n this.handlers.get(event)!.add(handler as EventHandler<unknown>);\r\n\r\n // Return unsubscribe function\r\n return () => this.off(event, handler);\r\n }\r\n\r\n /**\r\n * Register a one-time event handler\r\n */\r\n once<K extends PayrollEventType>(\r\n event: K,\r\n handler: PayrollEventHandler<K>\r\n ): () => void {\r\n const wrappedHandler: PayrollEventHandler<K> = async (payload) => {\r\n this.off(event, wrappedHandler);\r\n await handler(payload);\r\n };\r\n return this.on(event, wrappedHandler);\r\n }\r\n\r\n /**\r\n * Remove an event handler\r\n */\r\n off<K extends PayrollEventType>(\r\n event: K,\r\n handler: PayrollEventHandler<K>\r\n ): void {\r\n const eventHandlers = this.handlers.get(event);\r\n if (eventHandlers) {\r\n eventHandlers.delete(handler as EventHandler<unknown>);\r\n }\r\n }\r\n\r\n /**\r\n * Emit an event\r\n */\r\n async emit<K extends PayrollEventType>(\r\n event: K,\r\n payload: PayrollEventMap[K]\r\n ): Promise<void> {\r\n const eventHandlers = this.handlers.get(event);\r\n if (!eventHandlers || eventHandlers.size === 0) {\r\n return;\r\n }\r\n\r\n const handlers = Array.from(eventHandlers);\r\n await Promise.all(\r\n handlers.map(async (handler) => {\r\n try {\r\n await handler(payload);\r\n } catch (error) {\r\n console.error(`Event handler error for ${event}:`, error);\r\n }\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * Emit event synchronously (fire-and-forget)\r\n */\r\n emitSync<K extends PayrollEventType>(\r\n event: K,\r\n payload: PayrollEventMap[K]\r\n ): void {\r\n void this.emit(event, payload);\r\n }\r\n\r\n /**\r\n * Remove all handlers for an event\r\n */\r\n removeAllListeners(event?: PayrollEventType): void {\r\n if (event) {\r\n this.handlers.delete(event);\r\n } else {\r\n this.handlers.clear();\r\n }\r\n }\r\n\r\n /**\r\n * Get listener count for an event\r\n */\r\n listenerCount(event: PayrollEventType): number {\r\n return this.handlers.get(event)?.size ?? 0;\r\n }\r\n\r\n /**\r\n * Get all registered events\r\n */\r\n eventNames(): PayrollEventType[] {\r\n return Array.from(this.handlers.keys());\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Default EventBus Instance\r\n// ============================================================================\r\n\r\nlet defaultEventBus: EventBus | null = null;\r\n\r\n/**\r\n * Get or create the default event bus\r\n */\r\nexport function getEventBus(): EventBus {\r\n if (!defaultEventBus) {\r\n defaultEventBus = new EventBus();\r\n }\r\n return defaultEventBus;\r\n}\r\n\r\n/**\r\n * Create a new event bus instance\r\n */\r\nexport function createEventBus(): EventBus {\r\n return new EventBus();\r\n}\r\n\r\n/**\r\n * Reset the default event bus (for testing)\r\n */\r\nexport function resetEventBus(): void {\r\n if (defaultEventBus) {\r\n defaultEventBus.removeAllListeners();\r\n }\r\n defaultEventBus = null;\r\n}\r\n\r\n// ============================================================================\r\n// Convenience Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Subscribe to employee hired events\r\n */\r\nexport function onEmployeeHired(\r\n handler: PayrollEventHandler<'employee:hired'>\r\n): () => void {\r\n return getEventBus().on('employee:hired', handler);\r\n}\r\n\r\n/**\r\n * Subscribe to salary processed events\r\n */\r\nexport function onSalaryProcessed(\r\n handler: PayrollEventHandler<'salary:processed'>\r\n): () => void {\r\n return getEventBus().on('salary:processed', handler);\r\n}\r\n\r\n/**\r\n * Subscribe to payroll completed events\r\n */\r\nexport function onPayrollCompleted(\r\n handler: PayrollEventHandler<'payroll:completed'>\r\n): () => void {\r\n return getEventBus().on('payroll:completed', handler);\r\n}\r\n\r\n/**\r\n * Subscribe to milestone achieved events\r\n */\r\nexport function onMilestoneAchieved(\r\n handler: PayrollEventHandler<'milestone:achieved'>\r\n): () => void {\r\n return getEventBus().on('milestone:achieved', handler);\r\n}\r\n\r\n","/**\r\n * @classytic/payroll - Plugin System\r\n *\r\n * Extensible plugin architecture for customization\r\n * Follows patterns from popular libraries like Mongoose, Fastify\r\n */\r\n\r\nimport type { PayrollInstance, PayrollPlugin, Logger } from '../types.js';\r\nimport type { EventBus, PayrollEventType, PayrollEventMap } from './events.js';\r\n\r\n// ============================================================================\r\n// Plugin Context\r\n// ============================================================================\r\n\r\nexport interface PluginContext {\r\n /** Payroll instance */\r\n payroll: PayrollInstance;\r\n /** Event bus for subscribing to events */\r\n events: EventBus;\r\n /** Logger instance */\r\n logger: PluginLogger;\r\n /** Configuration getter */\r\n getConfig: <T>(key: string) => T | undefined;\r\n /** Register a hook */\r\n addHook: <K extends PayrollEventType>(\r\n event: K,\r\n handler: (payload: PayrollEventMap[K]) => void | Promise<void>\r\n ) => () => void;\r\n}\r\n\r\nexport interface PluginLogger {\r\n info(message: string, meta?: Record<string, unknown>): void;\r\n error(message: string, meta?: Record<string, unknown>): void;\r\n warn(message: string, meta?: Record<string, unknown>): void;\r\n debug(message: string, meta?: Record<string, unknown>): void;\r\n}\r\n\r\n// ============================================================================\r\n// Plugin Hooks\r\n// ============================================================================\r\n\r\nexport interface PluginHooks {\r\n /** Called before employee is hired */\r\n beforeHire?: (params: unknown) => void | Promise<void>;\r\n /** Called after employee is hired */\r\n afterHire?: (employee: unknown) => void | Promise<void>;\r\n /** Called before salary is processed */\r\n beforeProcessSalary?: (params: unknown) => void | Promise<void>;\r\n /** Called after salary is processed */\r\n afterProcessSalary?: (result: unknown) => void | Promise<void>;\r\n /** Called before termination */\r\n beforeTerminate?: (params: unknown) => void | Promise<void>;\r\n /** Called after termination */\r\n afterTerminate?: (employee: unknown) => void | Promise<void>;\r\n /** Called on any error */\r\n onError?: (error: Error, context: string) => void | Promise<void>;\r\n}\r\n\r\n// ============================================================================\r\n// ClockIn Plugin Interface\r\n// ============================================================================\r\n\r\nexport interface PayrollPluginDefinition {\r\n name: string;\r\n version?: string;\r\n hooks?: PluginHooks;\r\n init?: (context: PluginContext) => void | Promise<void>;\r\n destroy?: () => void | Promise<void>;\r\n}\r\n\r\n// ============================================================================\r\n// Plugin Manager\r\n// ============================================================================\r\n\r\nexport class PluginManager {\r\n private plugins = new Map<string, PayrollPluginDefinition>();\r\n private hooks = new Map<keyof PluginHooks, Array<NonNullable<PluginHooks[keyof PluginHooks]>>>();\r\n\r\n constructor(private context: PluginContext) {}\r\n\r\n /**\r\n * Register a plugin\r\n */\r\n async register(plugin: PayrollPluginDefinition): Promise<void> {\r\n if (this.plugins.has(plugin.name)) {\r\n throw new Error(`Plugin \"${plugin.name}\" is already registered`);\r\n }\r\n\r\n // Register hooks\r\n if (plugin.hooks) {\r\n for (const [hookName, handler] of Object.entries(plugin.hooks)) {\r\n if (handler) {\r\n this.addHook(hookName as keyof PluginHooks, handler);\r\n }\r\n }\r\n }\r\n\r\n // Initialize plugin\r\n if (plugin.init) {\r\n await plugin.init(this.context);\r\n }\r\n\r\n this.plugins.set(plugin.name, plugin);\r\n this.context.logger.debug(`Plugin \"${plugin.name}\" registered`);\r\n }\r\n\r\n /**\r\n * Unregister a plugin\r\n */\r\n async unregister(name: string): Promise<void> {\r\n const plugin = this.plugins.get(name);\r\n if (!plugin) {\r\n return;\r\n }\r\n\r\n if (plugin.destroy) {\r\n await plugin.destroy();\r\n }\r\n\r\n this.plugins.delete(name);\r\n this.context.logger.debug(`Plugin \"${name}\" unregistered`);\r\n }\r\n\r\n /**\r\n * Add a hook handler\r\n */\r\n private addHook<K extends keyof PluginHooks>(\r\n hookName: K,\r\n handler: NonNullable<PluginHooks[K]>\r\n ): void {\r\n if (!this.hooks.has(hookName)) {\r\n this.hooks.set(hookName, []);\r\n }\r\n this.hooks.get(hookName)!.push(handler);\r\n }\r\n\r\n /**\r\n * Execute hooks for a given event\r\n */\r\n async executeHooks<K extends keyof PluginHooks>(\r\n hookName: K,\r\n ...args: Parameters<NonNullable<PluginHooks[K]>>\r\n ): Promise<void> {\r\n const handlers = this.hooks.get(hookName);\r\n if (!handlers || handlers.length === 0) {\r\n return;\r\n }\r\n\r\n for (const handler of handlers) {\r\n try {\r\n await (handler as (...args: unknown[]) => void | Promise<void>)(...args);\r\n } catch (error) {\r\n this.context.logger.error(`Hook \"${hookName}\" error:`, { error });\r\n // Execute onError hooks\r\n const errorHandlers = this.hooks.get('onError');\r\n if (errorHandlers) {\r\n for (const errorHandler of errorHandlers) {\r\n try {\r\n await (errorHandler as PluginHooks['onError'])!(error as Error, hookName);\r\n } catch {\r\n // Ignore errors in error handlers\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get registered plugin names\r\n */\r\n getPluginNames(): string[] {\r\n return Array.from(this.plugins.keys());\r\n }\r\n\r\n /**\r\n * Check if plugin is registered\r\n */\r\n hasPlugin(name: string): boolean {\r\n return this.plugins.has(name);\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Plugin Definition Helper\r\n// ============================================================================\r\n\r\n/**\r\n * Define a plugin with type safety\r\n */\r\nexport function definePlugin(\r\n definition: PayrollPluginDefinition\r\n): PayrollPluginDefinition {\r\n return definition;\r\n}\r\n\r\n// ============================================================================\r\n// Built-in Plugins\r\n// ============================================================================\r\n\r\n/**\r\n * Logging plugin - logs all payroll events\r\n */\r\nexport const loggingPlugin = definePlugin({\r\n name: 'logging',\r\n version: '1.0.0',\r\n init: (context) => {\r\n // Subscribe to all events\r\n context.addHook('employee:hired', (payload) => {\r\n context.logger.info('Employee hired', {\r\n employeeId: payload.employee.employeeId,\r\n position: payload.employee.position,\r\n });\r\n });\r\n\r\n context.addHook('salary:processed', (payload) => {\r\n context.logger.info('Salary processed', {\r\n employeeId: payload.employee.employeeId,\r\n amount: payload.payroll.netAmount,\r\n period: payload.payroll.period,\r\n });\r\n });\r\n\r\n context.addHook('employee:terminated', (payload) => {\r\n context.logger.info('Employee terminated', {\r\n employeeId: payload.employee.employeeId,\r\n reason: payload.reason,\r\n });\r\n });\r\n },\r\n hooks: {\r\n onError: (error, context) => {\r\n console.error(`[Payroll Error] ${context}:`, error.message);\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Metrics plugin - collects payroll metrics\r\n */\r\nexport const metricsPlugin = definePlugin({\r\n name: 'metrics',\r\n version: '1.0.0',\r\n init: (context) => {\r\n const metrics = {\r\n employeesHired: 0,\r\n employeesTerminated: 0,\r\n salariesProcessed: 0,\r\n totalPaid: 0,\r\n errors: 0,\r\n };\r\n\r\n context.addHook('employee:hired', () => {\r\n metrics.employeesHired++;\r\n });\r\n\r\n context.addHook('employee:terminated', () => {\r\n metrics.employeesTerminated++;\r\n });\r\n\r\n context.addHook('salary:processed', (payload) => {\r\n metrics.salariesProcessed++;\r\n metrics.totalPaid += payload.payroll.netAmount;\r\n });\r\n\r\n // Expose metrics on payroll instance\r\n (context.payroll as unknown as { metrics: typeof metrics }).metrics = metrics;\r\n },\r\n hooks: {\r\n onError: (error, context) => {\r\n // Increment error counter\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Notification plugin - sends notifications for events\r\n */\r\nexport interface NotificationPluginOptions {\r\n onHired?: (employee: { id: unknown; name?: string }) => void | Promise<void>;\r\n onTerminated?: (employee: { id: unknown; name?: string }) => void | Promise<void>;\r\n onSalaryProcessed?: (details: { \r\n employee: { id: unknown; name?: string };\r\n amount: number;\r\n }) => void | Promise<void>;\r\n onMilestone?: (details: {\r\n employee: { id: unknown; name?: string };\r\n milestone: string;\r\n }) => void | Promise<void>;\r\n}\r\n\r\nexport function createNotificationPlugin(\r\n options: NotificationPluginOptions\r\n): PayrollPluginDefinition {\r\n return definePlugin({\r\n name: 'notification',\r\n version: '1.0.0',\r\n init: (context) => {\r\n if (options.onHired) {\r\n context.addHook('employee:hired', async (payload) => {\r\n await options.onHired!({\r\n id: payload.employee.id,\r\n name: payload.employee.position,\r\n });\r\n });\r\n }\r\n\r\n if (options.onTerminated) {\r\n context.addHook('employee:terminated', async (payload) => {\r\n await options.onTerminated!({\r\n id: payload.employee.id,\r\n name: payload.employee.name,\r\n });\r\n });\r\n }\r\n\r\n if (options.onSalaryProcessed) {\r\n context.addHook('salary:processed', async (payload) => {\r\n await options.onSalaryProcessed!({\r\n employee: {\r\n id: payload.employee.id,\r\n name: payload.employee.name,\r\n },\r\n amount: payload.payroll.netAmount,\r\n });\r\n });\r\n }\r\n\r\n if (options.onMilestone) {\r\n context.addHook('milestone:achieved', async (payload) => {\r\n await options.onMilestone!({\r\n employee: {\r\n id: payload.employee.id,\r\n name: payload.employee.name,\r\n },\r\n milestone: payload.milestone.message,\r\n });\r\n });\r\n }\r\n },\r\n });\r\n}\r\n\r\n// Alias for backwards compatibility\r\nexport const notificationPlugin = createNotificationPlugin({});\r\n\r\n","/**\r\n * @classytic/payroll - Date Utilities\r\n *\r\n * Pure, composable, testable date operations\r\n * No side effects, no mutations\r\n */\r\n\r\nimport type { PayPeriodInfo, PaymentFrequency } from '../types.js';\r\n\r\n// ============================================================================\r\n// Date Arithmetic\r\n// ============================================================================\r\n\r\n/**\r\n * Add days to a date\r\n */\r\nexport function addDays(date: Date, days: number): Date {\r\n const result = new Date(date);\r\n result.setDate(result.getDate() + days);\r\n return result;\r\n}\r\n\r\n/**\r\n * Add months to a date\r\n */\r\nexport function addMonths(date: Date, months: number): Date {\r\n const result = new Date(date);\r\n result.setMonth(result.getMonth() + months);\r\n return result;\r\n}\r\n\r\n/**\r\n * Add years to a date\r\n */\r\nexport function addYears(date: Date, years: number): Date {\r\n const result = new Date(date);\r\n result.setFullYear(result.getFullYear() + years);\r\n return result;\r\n}\r\n\r\n/**\r\n * Subtract days from a date\r\n */\r\nexport function subDays(date: Date, days: number): Date {\r\n return addDays(date, -days);\r\n}\r\n\r\n/**\r\n * Subtract months from a date\r\n */\r\nexport function subMonths(date: Date, months: number): Date {\r\n return addMonths(date, -months);\r\n}\r\n\r\n// ============================================================================\r\n// Date Boundaries\r\n// ============================================================================\r\n\r\n/**\r\n * Get the start of a month\r\n */\r\nexport function startOfMonth(date: Date): Date {\r\n const result = new Date(date);\r\n result.setDate(1);\r\n result.setHours(0, 0, 0, 0);\r\n return result;\r\n}\r\n\r\n/**\r\n * Get the end of a month\r\n */\r\nexport function endOfMonth(date: Date): Date {\r\n const result = new Date(date);\r\n result.setMonth(result.getMonth() + 1, 0);\r\n result.setHours(23, 59, 59, 999);\r\n return result;\r\n}\r\n\r\n/**\r\n * Get the start of a year\r\n */\r\nexport function startOfYear(date: Date): Date {\r\n const result = new Date(date);\r\n result.setMonth(0, 1);\r\n result.setHours(0, 0, 0, 0);\r\n return result;\r\n}\r\n\r\n/**\r\n * Get the end of a year\r\n */\r\nexport function endOfYear(date: Date): Date {\r\n const result = new Date(date);\r\n result.setMonth(11, 31);\r\n result.setHours(23, 59, 59, 999);\r\n return result;\r\n}\r\n\r\n/**\r\n * Get the start of a day\r\n */\r\nexport function startOfDay(date: Date): Date {\r\n const result = new Date(date);\r\n result.setHours(0, 0, 0, 0);\r\n return result;\r\n}\r\n\r\n/**\r\n * Get the end of a day\r\n */\r\nexport function endOfDay(date: Date): Date {\r\n const result = new Date(date);\r\n result.setHours(23, 59, 59, 999);\r\n return result;\r\n}\r\n\r\n// ============================================================================\r\n// Date Differences\r\n// ============================================================================\r\n\r\n/**\r\n * Calculate difference in days between two dates\r\n */\r\nexport function diffInDays(start: Date, end: Date): number {\r\n return Math.ceil(\r\n (new Date(end).getTime() - new Date(start).getTime()) / (1000 * 60 * 60 * 24)\r\n );\r\n}\r\n\r\n/**\r\n * Calculate difference in months between two dates\r\n */\r\nexport function diffInMonths(start: Date, end: Date): number {\r\n const startDate = new Date(start);\r\n const endDate = new Date(end);\r\n return (\r\n (endDate.getFullYear() - startDate.getFullYear()) * 12 +\r\n (endDate.getMonth() - startDate.getMonth())\r\n );\r\n}\r\n\r\n/**\r\n * Calculate difference in years between two dates\r\n */\r\nexport function diffInYears(start: Date, end: Date): number {\r\n return Math.floor(diffInMonths(start, end) / 12);\r\n}\r\n\r\n// Aliases for backwards compatibility\r\nexport const daysBetween = diffInDays;\r\nexport const monthsBetween = diffInMonths;\r\n\r\n// ============================================================================\r\n// Day Type Checks\r\n// ============================================================================\r\n\r\n/**\r\n * Check if date is a weekday (Mon-Fri)\r\n */\r\nexport function isWeekday(date: Date): boolean {\r\n const day = new Date(date).getDay();\r\n return day >= 1 && day <= 5;\r\n}\r\n\r\n/**\r\n * Check if date is a weekend (Sat-Sun)\r\n */\r\nexport function isWeekend(date: Date): boolean {\r\n const day = new Date(date).getDay();\r\n return day === 0 || day === 6;\r\n}\r\n\r\n/**\r\n * Get day of week (0=Sunday, 6=Saturday)\r\n */\r\nexport function getDayOfWeek(date: Date): number {\r\n return new Date(date).getDay();\r\n}\r\n\r\n/**\r\n * Get day name\r\n */\r\nexport function getDayName(date: Date): string {\r\n const days = [\r\n 'Sunday',\r\n 'Monday',\r\n 'Tuesday',\r\n 'Wednesday',\r\n 'Thursday',\r\n 'Friday',\r\n 'Saturday',\r\n ];\r\n return days[getDayOfWeek(date)];\r\n}\r\n\r\n// ============================================================================\r\n// Pay Period Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Get pay period for a given month and year\r\n */\r\nexport function getPayPeriod(month: number, year: number): PayPeriodInfo {\r\n const startDate = new Date(year, month - 1, 1);\r\n return {\r\n month,\r\n year,\r\n startDate: startOfMonth(startDate),\r\n endDate: endOfMonth(startDate),\r\n };\r\n}\r\n\r\n/**\r\n * Get current pay period\r\n */\r\nexport function getCurrentPeriod(date = new Date()): { year: number; month: number } {\r\n const d = new Date(date);\r\n return {\r\n year: d.getFullYear(),\r\n month: d.getMonth() + 1,\r\n };\r\n}\r\n\r\n/**\r\n * Get working days in a month\r\n */\r\nexport function getWorkingDaysInMonth(year: number, month: number): number {\r\n const start = new Date(year, month - 1, 1);\r\n const end = endOfMonth(start);\r\n let count = 0;\r\n \r\n const current = new Date(start);\r\n while (current <= end) {\r\n if (isWeekday(current)) {\r\n count++;\r\n }\r\n current.setDate(current.getDate() + 1);\r\n }\r\n \r\n return count;\r\n}\r\n\r\n/**\r\n * Get total days in a month\r\n */\r\nexport function getDaysInMonth(year: number, month: number): number {\r\n return new Date(year, month, 0).getDate();\r\n}\r\n\r\n// ============================================================================\r\n// Employment Date Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Calculate probation end date\r\n */\r\nexport function calculateProbationEnd(\r\n hireDate: Date,\r\n probationMonths: number\r\n): Date | null {\r\n if (!probationMonths || probationMonths <= 0) return null;\r\n return addMonths(hireDate, probationMonths);\r\n}\r\n\r\n/**\r\n * Check if employee is on probation\r\n */\r\nexport function isOnProbation(\r\n probationEndDate: Date | null | undefined,\r\n now = new Date()\r\n): boolean {\r\n if (!probationEndDate) return false;\r\n return now < new Date(probationEndDate);\r\n}\r\n\r\n/**\r\n * Calculate years of service\r\n */\r\nexport function calculateYearsOfService(\r\n hireDate: Date,\r\n terminationDate?: Date | null\r\n): number {\r\n const end = terminationDate || new Date();\r\n const days = diffInDays(hireDate, end);\r\n return Math.max(0, Math.floor((days / 365.25) * 10) / 10);\r\n}\r\n\r\n// ============================================================================\r\n// Range Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Check if a date is within a range\r\n */\r\nexport function isDateInRange(date: Date, start: Date, end: Date): boolean {\r\n const checkDate = new Date(date);\r\n return checkDate >= new Date(start) && checkDate <= new Date(end);\r\n}\r\n\r\n/**\r\n * Get date range for a pay period\r\n */\r\nexport function getPayPeriodDateRange(\r\n month: number,\r\n year: number\r\n): { start: Date; end: Date } {\r\n const period = getPayPeriod(month, year);\r\n return { start: period.startDate, end: period.endDate };\r\n}\r\n\r\n// ============================================================================\r\n// Formatting Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Format date for database storage\r\n */\r\nexport function formatDateForDB(date: Date): string {\r\n if (!date) return '';\r\n return new Date(date).toISOString();\r\n}\r\n\r\n/**\r\n * Parse date from database\r\n */\r\nexport function parseDBDate(dateString: string): Date | null {\r\n if (!dateString) return null;\r\n return new Date(dateString);\r\n}\r\n\r\n/**\r\n * Format period as string (e.g., \"01/2025\")\r\n */\r\nexport function formatPeriod({ month, year }: { month: number; year: number }): string {\r\n return `${String(month).padStart(2, '0')}/${year}`;\r\n}\r\n\r\n/**\r\n * Parse period string back to object\r\n */\r\nexport function parsePeriod(periodString: string): { month: number; year: number } {\r\n const [month, year] = periodString.split('/').map(Number);\r\n return { month, year };\r\n}\r\n\r\n/**\r\n * Format month name\r\n */\r\nexport function getMonthName(month: number): string {\r\n const months = [\r\n 'January', 'February', 'March', 'April', 'May', 'June',\r\n 'July', 'August', 'September', 'October', 'November', 'December',\r\n ];\r\n return months[month - 1] || '';\r\n}\r\n\r\n/**\r\n * Format short month name\r\n */\r\nexport function getShortMonthName(month: number): string {\r\n const months = [\r\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\r\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',\r\n ];\r\n return months[month - 1] || '';\r\n}\r\n\r\n// ============================================================================\r\n// Default Export\r\n// ============================================================================\r\n\r\nexport default {\r\n addDays,\r\n addMonths,\r\n addYears,\r\n subDays,\r\n subMonths,\r\n startOfMonth,\r\n endOfMonth,\r\n startOfYear,\r\n endOfYear,\r\n startOfDay,\r\n endOfDay,\r\n diffInDays,\r\n diffInMonths,\r\n diffInYears,\r\n daysBetween,\r\n monthsBetween,\r\n isWeekday,\r\n isWeekend,\r\n getDayOfWeek,\r\n getDayName,\r\n getPayPeriod,\r\n getCurrentPeriod,\r\n getWorkingDaysInMonth,\r\n getDaysInMonth,\r\n calculateProbationEnd,\r\n isOnProbation,\r\n calculateYearsOfService,\r\n isDateInRange,\r\n getPayPeriodDateRange,\r\n formatDateForDB,\r\n parseDBDate,\r\n formatPeriod,\r\n parsePeriod,\r\n getMonthName,\r\n getShortMonthName,\r\n};\r\n\r\n","/**\r\n * @classytic/payroll - Employee Factory\r\n *\r\n * Clean object creation for employee documents\r\n * Builder pattern for fluent API\r\n */\r\n\r\nimport type {\r\n ObjectIdLike,\r\n EmploymentType,\r\n Department,\r\n Compensation,\r\n BankDetails,\r\n WorkSchedule,\r\n Allowance,\r\n Deduction,\r\n PaymentFrequency,\r\n TerminationReason,\r\n} from '../types.js';\r\nimport { calculateProbationEnd } from '../utils/date.js';\r\nimport { HRM_CONFIG } from '../config.js';\r\n\r\n// ============================================================================\r\n// Employee Factory Types\r\n// ============================================================================\r\n\r\nexport interface CreateEmployeeParams {\r\n userId: ObjectIdLike;\r\n organizationId: ObjectIdLike;\r\n employment: {\r\n employeeId?: string;\r\n type?: EmploymentType;\r\n department?: Department | string;\r\n position: string;\r\n hireDate?: Date;\r\n probationMonths?: number;\r\n workSchedule?: WorkSchedule;\r\n };\r\n compensation: {\r\n baseAmount: number;\r\n frequency?: PaymentFrequency;\r\n currency?: string;\r\n allowances?: Array<Partial<Allowance>>;\r\n deductions?: Array<Partial<Deduction>>;\r\n };\r\n bankDetails?: BankDetails;\r\n}\r\n\r\nexport interface EmployeeData {\r\n userId: ObjectIdLike;\r\n organizationId: ObjectIdLike;\r\n employeeId: string;\r\n employmentType: EmploymentType;\r\n status: 'active';\r\n department?: Department;\r\n position: string;\r\n hireDate: Date;\r\n probationEndDate: Date | null;\r\n compensation: Compensation;\r\n workSchedule: WorkSchedule;\r\n bankDetails: BankDetails;\r\n payrollStats: {\r\n totalPaid: number;\r\n paymentsThisYear: number;\r\n averageMonthly: number;\r\n };\r\n}\r\n\r\nexport interface TerminationData {\r\n terminatedAt: Date;\r\n terminationReason: TerminationReason;\r\n terminationNotes?: string;\r\n terminatedBy: {\r\n userId?: ObjectIdLike;\r\n name?: string;\r\n role?: string;\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Employee Factory\r\n// ============================================================================\r\n\r\nexport class EmployeeFactory {\r\n /**\r\n * Create employee data object\r\n */\r\n static create(params: CreateEmployeeParams): EmployeeData {\r\n const { userId, organizationId, employment, compensation, bankDetails } = params;\r\n const hireDate = employment.hireDate || new Date();\r\n\r\n return {\r\n userId,\r\n organizationId,\r\n employeeId: employment.employeeId || `EMP-${Date.now()}-${Math.random().toString(36).substr(2, 6).toUpperCase()}`,\r\n employmentType: employment.type || 'full_time',\r\n status: 'active',\r\n department: employment.department as Department | undefined,\r\n position: employment.position,\r\n hireDate,\r\n probationEndDate: calculateProbationEnd(\r\n hireDate,\r\n employment.probationMonths ?? HRM_CONFIG.employment.defaultProbationMonths\r\n ),\r\n compensation: this.createCompensation(compensation),\r\n workSchedule: employment.workSchedule || this.defaultWorkSchedule(),\r\n bankDetails: bankDetails || {},\r\n payrollStats: {\r\n totalPaid: 0,\r\n paymentsThisYear: 0,\r\n averageMonthly: 0,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Create compensation object\r\n */\r\n static createCompensation(params: {\r\n baseAmount: number;\r\n frequency?: PaymentFrequency;\r\n currency?: string;\r\n allowances?: Array<Partial<Allowance>>;\r\n deductions?: Array<Partial<Deduction>>;\r\n }): Compensation {\r\n return {\r\n baseAmount: params.baseAmount,\r\n frequency: params.frequency || 'monthly',\r\n currency: params.currency || HRM_CONFIG.payroll.defaultCurrency,\r\n allowances: (params.allowances || []).map((a) => ({\r\n type: a.type || 'other',\r\n name: a.name || a.type || 'other',\r\n amount: a.amount || 0,\r\n taxable: a.taxable,\r\n recurring: a.recurring,\r\n effectiveFrom: a.effectiveFrom,\r\n effectiveTo: a.effectiveTo,\r\n })),\r\n deductions: (params.deductions || []).map((d) => ({\r\n type: d.type || 'other',\r\n name: d.name || d.type || 'other',\r\n amount: d.amount || 0,\r\n auto: d.auto,\r\n recurring: d.recurring,\r\n description: d.description,\r\n effectiveFrom: d.effectiveFrom,\r\n effectiveTo: d.effectiveTo,\r\n })),\r\n grossSalary: 0,\r\n netSalary: 0,\r\n effectiveFrom: new Date(),\r\n lastModified: new Date(),\r\n };\r\n }\r\n\r\n /**\r\n * Create allowance object\r\n */\r\n static createAllowance(params: {\r\n type: Allowance['type'];\r\n amount: number;\r\n name?: string;\r\n isPercentage?: boolean;\r\n taxable?: boolean;\r\n recurring?: boolean;\r\n }): Allowance {\r\n return {\r\n type: params.type,\r\n name: params.name || params.type,\r\n amount: params.amount,\r\n isPercentage: params.isPercentage ?? false,\r\n taxable: params.taxable ?? true,\r\n recurring: params.recurring ?? true,\r\n effectiveFrom: new Date(),\r\n };\r\n }\r\n\r\n /**\r\n * Create deduction object\r\n */\r\n static createDeduction(params: {\r\n type: Deduction['type'];\r\n amount: number;\r\n name?: string;\r\n isPercentage?: boolean;\r\n auto?: boolean;\r\n recurring?: boolean;\r\n description?: string;\r\n }): Deduction {\r\n return {\r\n type: params.type,\r\n name: params.name || params.type,\r\n amount: params.amount,\r\n isPercentage: params.isPercentage ?? false,\r\n auto: params.auto ?? false,\r\n recurring: params.recurring ?? true,\r\n description: params.description,\r\n effectiveFrom: new Date(),\r\n };\r\n }\r\n\r\n /**\r\n * Default work schedule\r\n */\r\n static defaultWorkSchedule(): WorkSchedule {\r\n return {\r\n hoursPerWeek: 40,\r\n hoursPerDay: 8,\r\n workingDays: [1, 2, 3, 4, 5], // Mon-Fri\r\n shiftStart: '09:00',\r\n shiftEnd: '17:00',\r\n };\r\n }\r\n\r\n /**\r\n * Create termination data\r\n */\r\n static createTermination(params: {\r\n reason: TerminationReason;\r\n date?: Date;\r\n notes?: string;\r\n context?: {\r\n userId?: ObjectIdLike;\r\n userName?: string;\r\n userRole?: string;\r\n };\r\n }): TerminationData {\r\n return {\r\n terminatedAt: params.date || new Date(),\r\n terminationReason: params.reason,\r\n terminationNotes: params.notes,\r\n terminatedBy: {\r\n userId: params.context?.userId,\r\n name: params.context?.userName,\r\n role: params.context?.userRole,\r\n },\r\n };\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Employee Builder\r\n// ============================================================================\r\n\r\nexport class EmployeeBuilder {\r\n private data: Partial<CreateEmployeeParams> = {\r\n employment: {} as CreateEmployeeParams['employment'],\r\n compensation: {} as CreateEmployeeParams['compensation'],\r\n bankDetails: {},\r\n };\r\n\r\n /**\r\n * Set user ID\r\n */\r\n forUser(userId: ObjectIdLike): this {\r\n this.data.userId = userId;\r\n return this;\r\n }\r\n\r\n /**\r\n * Set organization ID\r\n */\r\n inOrganization(organizationId: ObjectIdLike): this {\r\n this.data.organizationId = organizationId;\r\n return this;\r\n }\r\n\r\n /**\r\n * Set employee ID\r\n */\r\n withEmployeeId(employeeId: string): this {\r\n this.data.employment = { ...this.data.employment!, employeeId };\r\n return this;\r\n }\r\n\r\n /**\r\n * Set department\r\n */\r\n inDepartment(department: Department): this {\r\n this.data.employment = { ...this.data.employment!, department };\r\n return this;\r\n }\r\n\r\n /**\r\n * Set position\r\n */\r\n asPosition(position: string): this {\r\n this.data.employment = { ...this.data.employment!, position };\r\n return this;\r\n }\r\n\r\n /**\r\n * Set employment type\r\n */\r\n withEmploymentType(type: EmploymentType): this {\r\n this.data.employment = { ...this.data.employment!, type };\r\n return this;\r\n }\r\n\r\n /**\r\n * Set hire date\r\n */\r\n hiredOn(date: Date): this {\r\n this.data.employment = { ...this.data.employment!, hireDate: date };\r\n return this;\r\n }\r\n\r\n /**\r\n * Set probation period\r\n */\r\n withProbation(months: number): this {\r\n this.data.employment = { ...this.data.employment!, probationMonths: months };\r\n return this;\r\n }\r\n\r\n /**\r\n * Set work schedule\r\n */\r\n withSchedule(schedule: WorkSchedule): this {\r\n this.data.employment = { ...this.data.employment!, workSchedule: schedule };\r\n return this;\r\n }\r\n\r\n /**\r\n * Set base salary\r\n */\r\n withBaseSalary(\r\n amount: number,\r\n frequency: PaymentFrequency = 'monthly',\r\n currency = 'BDT'\r\n ): this {\r\n this.data.compensation = {\r\n ...this.data.compensation!,\r\n baseAmount: amount,\r\n frequency,\r\n currency,\r\n };\r\n return this;\r\n }\r\n\r\n /**\r\n * Add allowance\r\n */\r\n addAllowance(\r\n type: Allowance['type'],\r\n amount: number,\r\n options: { taxable?: boolean; recurring?: boolean } = {}\r\n ): this {\r\n const allowances = this.data.compensation?.allowances || [];\r\n this.data.compensation = {\r\n ...this.data.compensation!,\r\n allowances: [\r\n ...allowances,\r\n { type, amount, taxable: options.taxable, recurring: options.recurring },\r\n ],\r\n };\r\n return this;\r\n }\r\n\r\n /**\r\n * Add deduction\r\n */\r\n addDeduction(\r\n type: Deduction['type'],\r\n amount: number,\r\n options: { auto?: boolean; recurring?: boolean; description?: string } = {}\r\n ): this {\r\n const deductions = this.data.compensation?.deductions || [];\r\n this.data.compensation = {\r\n ...this.data.compensation!,\r\n deductions: [\r\n ...deductions,\r\n {\r\n type,\r\n amount,\r\n auto: options.auto,\r\n recurring: options.recurring,\r\n description: options.description,\r\n },\r\n ],\r\n };\r\n return this;\r\n }\r\n\r\n /**\r\n * Set bank details\r\n */\r\n withBankDetails(bankDetails: BankDetails): this {\r\n this.data.bankDetails = bankDetails;\r\n return this;\r\n }\r\n\r\n /**\r\n * Build employee data\r\n */\r\n build(): EmployeeData {\r\n if (!this.data.userId || !this.data.organizationId) {\r\n throw new Error('userId and organizationId are required');\r\n }\r\n if (!this.data.employment?.employeeId || !this.data.employment?.position) {\r\n throw new Error('employeeId and position are required');\r\n }\r\n if (!this.data.compensation?.baseAmount) {\r\n throw new Error('baseAmount is required');\r\n }\r\n\r\n return EmployeeFactory.create(this.data as CreateEmployeeParams);\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Factory Function\r\n// ============================================================================\r\n\r\n/**\r\n * Create new employee builder\r\n */\r\nexport function createEmployee(): EmployeeBuilder {\r\n return new EmployeeBuilder();\r\n}\r\n\r\n// ============================================================================\r\n// Default Export\r\n// ============================================================================\r\n\r\nexport default {\r\n EmployeeFactory,\r\n EmployeeBuilder,\r\n createEmployee,\r\n};\r\n\r\n","/**\r\n * @classytic/payroll - Enums\r\n *\r\n * Type-safe enum definitions with const assertions\r\n * Single source of truth for all enum values\r\n */\r\n\r\nimport type {\r\n EmploymentType,\r\n EmployeeStatus,\r\n Department,\r\n PaymentFrequency,\r\n PaymentMethod,\r\n AllowanceType,\r\n DeductionType,\r\n PayrollStatus,\r\n TerminationReason,\r\n HRMTransactionCategory,\r\n SalaryBand,\r\n OrgRole,\r\n} from './types.js';\r\n\r\n// ============================================================================\r\n// Employment Type\r\n// ============================================================================\r\n\r\nexport const EMPLOYMENT_TYPE = {\r\n FULL_TIME: 'full_time',\r\n PART_TIME: 'part_time',\r\n CONTRACT: 'contract',\r\n INTERN: 'intern',\r\n CONSULTANT: 'consultant',\r\n} as const satisfies Record<string, EmploymentType>;\r\n\r\nexport const EMPLOYMENT_TYPE_VALUES = Object.values(EMPLOYMENT_TYPE);\r\n\r\nexport function isValidEmploymentType(value: string): value is EmploymentType {\r\n return EMPLOYMENT_TYPE_VALUES.includes(value as EmploymentType);\r\n}\r\n\r\n// ============================================================================\r\n// Employee Status\r\n// ============================================================================\r\n\r\nexport const EMPLOYEE_STATUS = {\r\n ACTIVE: 'active',\r\n ON_LEAVE: 'on_leave',\r\n SUSPENDED: 'suspended',\r\n TERMINATED: 'terminated',\r\n} as const satisfies Record<string, EmployeeStatus>;\r\n\r\nexport const EMPLOYEE_STATUS_VALUES = Object.values(EMPLOYEE_STATUS);\r\n\r\nexport function isValidEmployeeStatus(value: string): value is EmployeeStatus {\r\n return EMPLOYEE_STATUS_VALUES.includes(value as EmployeeStatus);\r\n}\r\n\r\nexport function isActiveStatus(status: EmployeeStatus): boolean {\r\n return status === EMPLOYEE_STATUS.ACTIVE;\r\n}\r\n\r\nexport function isEmployedStatus(status: EmployeeStatus): boolean {\r\n return status !== EMPLOYEE_STATUS.TERMINATED;\r\n}\r\n\r\nexport function canReceiveSalaryStatus(status: EmployeeStatus): boolean {\r\n return status === EMPLOYEE_STATUS.ACTIVE || status === EMPLOYEE_STATUS.ON_LEAVE;\r\n}\r\n\r\n// ============================================================================\r\n// Department\r\n// ============================================================================\r\n\r\nexport const DEPARTMENT = {\r\n MANAGEMENT: 'management',\r\n TRAINING: 'training',\r\n SALES: 'sales',\r\n OPERATIONS: 'operations',\r\n SUPPORT: 'support',\r\n HR: 'hr',\r\n MAINTENANCE: 'maintenance',\r\n MARKETING: 'marketing',\r\n FINANCE: 'finance',\r\n IT: 'it',\r\n} as const satisfies Record<string, Department>;\r\n\r\nexport const DEPARTMENT_VALUES = Object.values(DEPARTMENT);\r\n\r\nexport function isValidDepartment(value: string): value is Department {\r\n return DEPARTMENT_VALUES.includes(value as Department);\r\n}\r\n\r\n// ============================================================================\r\n// Payment Frequency\r\n// ============================================================================\r\n\r\nexport const PAYMENT_FREQUENCY = {\r\n MONTHLY: 'monthly',\r\n BI_WEEKLY: 'bi_weekly',\r\n WEEKLY: 'weekly',\r\n HOURLY: 'hourly',\r\n DAILY: 'daily',\r\n} as const satisfies Record<string, PaymentFrequency>;\r\n\r\nexport const PAYMENT_FREQUENCY_VALUES = Object.values(PAYMENT_FREQUENCY);\r\n\r\nexport function isValidPaymentFrequency(value: string): value is PaymentFrequency {\r\n return PAYMENT_FREQUENCY_VALUES.includes(value as PaymentFrequency);\r\n}\r\n\r\n// ============================================================================\r\n// Payment Method\r\n// ============================================================================\r\n\r\nexport const PAYMENT_METHOD = {\r\n BANK: 'bank',\r\n CASH: 'cash',\r\n MOBILE: 'mobile',\r\n BKASH: 'bkash',\r\n NAGAD: 'nagad',\r\n ROCKET: 'rocket',\r\n CHECK: 'check',\r\n} as const satisfies Record<string, PaymentMethod>;\r\n\r\nexport const PAYMENT_METHOD_VALUES = Object.values(PAYMENT_METHOD);\r\n\r\nexport function isValidPaymentMethod(value: string): value is PaymentMethod {\r\n return PAYMENT_METHOD_VALUES.includes(value as PaymentMethod);\r\n}\r\n\r\n// ============================================================================\r\n// Allowance Type\r\n// ============================================================================\r\n\r\nexport const ALLOWANCE_TYPE = {\r\n HOUSING: 'housing',\r\n TRANSPORT: 'transport',\r\n MEAL: 'meal',\r\n MOBILE: 'mobile',\r\n MEDICAL: 'medical',\r\n EDUCATION: 'education',\r\n BONUS: 'bonus',\r\n OTHER: 'other',\r\n} as const satisfies Record<string, AllowanceType>;\r\n\r\nexport const ALLOWANCE_TYPE_VALUES = Object.values(ALLOWANCE_TYPE);\r\n\r\nexport function isValidAllowanceType(value: string): value is AllowanceType {\r\n return ALLOWANCE_TYPE_VALUES.includes(value as AllowanceType);\r\n}\r\n\r\n// ============================================================================\r\n// Deduction Type\r\n// ============================================================================\r\n\r\nexport const DEDUCTION_TYPE = {\r\n TAX: 'tax',\r\n LOAN: 'loan',\r\n ADVANCE: 'advance',\r\n PROVIDENT_FUND: 'provident_fund',\r\n INSURANCE: 'insurance',\r\n ABSENCE: 'absence',\r\n OTHER: 'other',\r\n} as const satisfies Record<string, DeductionType>;\r\n\r\nexport const DEDUCTION_TYPE_VALUES = Object.values(DEDUCTION_TYPE);\r\n\r\nexport function isValidDeductionType(value: string): value is DeductionType {\r\n return DEDUCTION_TYPE_VALUES.includes(value as DeductionType);\r\n}\r\n\r\n// ============================================================================\r\n// Payroll Status\r\n// ============================================================================\r\n\r\nexport const PAYROLL_STATUS = {\r\n PENDING: 'pending',\r\n PROCESSING: 'processing',\r\n PAID: 'paid',\r\n FAILED: 'failed',\r\n CANCELLED: 'cancelled',\r\n} as const satisfies Record<string, PayrollStatus>;\r\n\r\nexport const PAYROLL_STATUS_VALUES = Object.values(PAYROLL_STATUS);\r\n\r\nexport function isValidPayrollStatus(value: string): value is PayrollStatus {\r\n return PAYROLL_STATUS_VALUES.includes(value as PayrollStatus);\r\n}\r\n\r\nexport function isCompletedPayrollStatus(status: PayrollStatus): boolean {\r\n return status === PAYROLL_STATUS.PAID;\r\n}\r\n\r\nexport function isPendingPayrollStatus(status: PayrollStatus): boolean {\r\n return status === PAYROLL_STATUS.PENDING || status === PAYROLL_STATUS.PROCESSING;\r\n}\r\n\r\n// ============================================================================\r\n// Termination Reason\r\n// ============================================================================\r\n\r\nexport const TERMINATION_REASON = {\r\n RESIGNATION: 'resignation',\r\n RETIREMENT: 'retirement',\r\n TERMINATION: 'termination',\r\n CONTRACT_END: 'contract_end',\r\n MUTUAL_AGREEMENT: 'mutual_agreement',\r\n OTHER: 'other',\r\n} as const satisfies Record<string, TerminationReason>;\r\n\r\nexport const TERMINATION_REASON_VALUES = Object.values(TERMINATION_REASON);\r\n\r\nexport function isValidTerminationReason(value: string): value is TerminationReason {\r\n return TERMINATION_REASON_VALUES.includes(value as TerminationReason);\r\n}\r\n\r\n// ============================================================================\r\n// HRM Transaction Categories\r\n// ============================================================================\r\n\r\nexport const HRM_TRANSACTION_CATEGORIES = {\r\n SALARY: 'salary',\r\n BONUS: 'bonus',\r\n COMMISSION: 'commission',\r\n OVERTIME: 'overtime',\r\n SEVERANCE: 'severance',\r\n} as const satisfies Record<string, HRMTransactionCategory>;\r\n\r\nexport const HRM_CATEGORY_VALUES = Object.values(HRM_TRANSACTION_CATEGORIES);\r\n\r\nexport function isHRMManagedCategory(category: string): category is HRMTransactionCategory {\r\n return HRM_CATEGORY_VALUES.includes(category as HRMTransactionCategory);\r\n}\r\n\r\n// ============================================================================\r\n// Salary Band\r\n// ============================================================================\r\n\r\nexport const SALARY_BAND = {\r\n INTERN: 'intern',\r\n JUNIOR: 'junior',\r\n MID: 'mid',\r\n SENIOR: 'senior',\r\n LEAD: 'lead',\r\n EXECUTIVE: 'executive',\r\n CUSTOM: 'custom',\r\n} as const satisfies Record<string, SalaryBand>;\r\n\r\nexport const SALARY_BAND_VALUES = Object.values(SALARY_BAND);\r\n\r\nexport function isValidSalaryBand(value: string): value is SalaryBand {\r\n return SALARY_BAND_VALUES.includes(value as SalaryBand);\r\n}\r\n\r\n// ============================================================================\r\n// Organization Role\r\n// ============================================================================\r\n\r\nexport const ORG_ROLE = {\r\n OWNER: 'owner',\r\n MANAGER: 'manager',\r\n TRAINER: 'trainer',\r\n STAFF: 'staff',\r\n INTERN: 'intern',\r\n CONSULTANT: 'consultant',\r\n} as const satisfies Record<string, OrgRole>;\r\n\r\nexport const ORG_ROLE_VALUES = Object.values(ORG_ROLE);\r\n\r\nexport function isValidOrgRole(value: string): value is OrgRole {\r\n return ORG_ROLE_VALUES.includes(value as OrgRole);\r\n}\r\n\r\n// ============================================================================\r\n// Default Export\r\n// ============================================================================\r\n\r\nexport default {\r\n EMPLOYMENT_TYPE,\r\n EMPLOYMENT_TYPE_VALUES,\r\n EMPLOYEE_STATUS,\r\n EMPLOYEE_STATUS_VALUES,\r\n DEPARTMENT,\r\n DEPARTMENT_VALUES,\r\n PAYMENT_FREQUENCY,\r\n PAYMENT_FREQUENCY_VALUES,\r\n PAYMENT_METHOD,\r\n PAYMENT_METHOD_VALUES,\r\n ALLOWANCE_TYPE,\r\n ALLOWANCE_TYPE_VALUES,\r\n DEDUCTION_TYPE,\r\n DEDUCTION_TYPE_VALUES,\r\n PAYROLL_STATUS,\r\n PAYROLL_STATUS_VALUES,\r\n TERMINATION_REASON,\r\n TERMINATION_REASON_VALUES,\r\n HRM_TRANSACTION_CATEGORIES,\r\n HRM_CATEGORY_VALUES,\r\n SALARY_BAND,\r\n SALARY_BAND_VALUES,\r\n ORG_ROLE,\r\n ORG_ROLE_VALUES,\r\n};\r\n\r\n","/**\r\n * @classytic/payroll - Query Builders\r\n *\r\n * Fluent API for building MongoDB queries\r\n * Type-safe, chainable, beautiful\r\n */\r\n\r\nimport mongoose, { Types } from 'mongoose';\r\nimport type {\r\n ObjectIdLike,\r\n EmployeeStatus,\r\n PayrollStatus,\r\n Department,\r\n EmploymentType,\r\n} from '../types.js';\r\n\r\n// ============================================================================\r\n// ObjectId Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Convert string or ObjectId to ObjectId\r\n */\r\nexport function toObjectId(id: ObjectIdLike): Types.ObjectId {\r\n if (id instanceof Types.ObjectId) return id;\r\n return new Types.ObjectId(id);\r\n}\r\n\r\n/**\r\n * Safely convert to ObjectId (returns null if invalid)\r\n */\r\nexport function safeToObjectId(id: unknown): Types.ObjectId | null {\r\n if (id instanceof Types.ObjectId) return id;\r\n if (typeof id === 'string' && Types.ObjectId.isValid(id)) {\r\n return new Types.ObjectId(id);\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * Check if value is valid ObjectId\r\n */\r\nexport function isValidObjectId(value: unknown): boolean {\r\n if (value instanceof Types.ObjectId) return true;\r\n if (typeof value === 'string') return Types.ObjectId.isValid(value);\r\n return false;\r\n}\r\n\r\n// ============================================================================\r\n// Base Query Builder\r\n// ============================================================================\r\n\r\nexport class QueryBuilder<T extends Record<string, unknown> = Record<string, unknown>> {\r\n protected query: T;\r\n\r\n constructor(initialQuery: T = {} as T) {\r\n this.query = { ...initialQuery };\r\n }\r\n\r\n /**\r\n * Add where condition\r\n */\r\n where<K extends string>(field: K, value: unknown): this {\r\n (this.query as Record<string, unknown>)[field] = value;\r\n return this;\r\n }\r\n\r\n /**\r\n * Add $in condition\r\n */\r\n whereIn<K extends string>(field: K, values: unknown[]): this {\r\n (this.query as Record<string, unknown>)[field] = { $in: values };\r\n return this;\r\n }\r\n\r\n /**\r\n * Add $nin condition\r\n */\r\n whereNotIn<K extends string>(field: K, values: unknown[]): this {\r\n (this.query as Record<string, unknown>)[field] = { $nin: values };\r\n return this;\r\n }\r\n\r\n /**\r\n * Add $gte condition\r\n */\r\n whereGte<K extends string>(field: K, value: unknown): this {\r\n const existing = (this.query as Record<string, Record<string, unknown>>)[field] || {};\r\n (this.query as Record<string, unknown>)[field] = { ...existing, $gte: value };\r\n return this;\r\n }\r\n\r\n /**\r\n * Add $lte condition\r\n */\r\n whereLte<K extends string>(field: K, value: unknown): this {\r\n const existing = (this.query as Record<string, Record<string, unknown>>)[field] || {};\r\n (this.query as Record<string, unknown>)[field] = { ...existing, $lte: value };\r\n return this;\r\n }\r\n\r\n /**\r\n * Add $gt condition\r\n */\r\n whereGt<K extends string>(field: K, value: unknown): this {\r\n const existing = (this.query as Record<string, Record<string, unknown>>)[field] || {};\r\n (this.query as Record<string, unknown>)[field] = { ...existing, $gt: value };\r\n return this;\r\n }\r\n\r\n /**\r\n * Add $lt condition\r\n */\r\n whereLt<K extends string>(field: K, value: unknown): this {\r\n const existing = (this.query as Record<string, Record<string, unknown>>)[field] || {};\r\n (this.query as Record<string, unknown>)[field] = { ...existing, $lt: value };\r\n return this;\r\n }\r\n\r\n /**\r\n * Add between condition\r\n */\r\n whereBetween<K extends string>(field: K, start: unknown, end: unknown): this {\r\n (this.query as Record<string, unknown>)[field] = { $gte: start, $lte: end };\r\n return this;\r\n }\r\n\r\n /**\r\n * Add $exists condition\r\n */\r\n whereExists<K extends string>(field: K): this {\r\n (this.query as Record<string, unknown>)[field] = { $exists: true };\r\n return this;\r\n }\r\n\r\n /**\r\n * Add $exists: false condition\r\n */\r\n whereNotExists<K extends string>(field: K): this {\r\n (this.query as Record<string, unknown>)[field] = { $exists: false };\r\n return this;\r\n }\r\n\r\n /**\r\n * Add $ne condition\r\n */\r\n whereNot<K extends string>(field: K, value: unknown): this {\r\n (this.query as Record<string, unknown>)[field] = { $ne: value };\r\n return this;\r\n }\r\n\r\n /**\r\n * Add regex condition\r\n */\r\n whereRegex<K extends string>(field: K, pattern: string, flags = 'i'): this {\r\n (this.query as Record<string, unknown>)[field] = { $regex: pattern, $options: flags };\r\n return this;\r\n }\r\n\r\n /**\r\n * Merge another query\r\n */\r\n merge(otherQuery: Record<string, unknown>): this {\r\n this.query = { ...this.query, ...otherQuery } as T;\r\n return this;\r\n }\r\n\r\n /**\r\n * Build and return the query\r\n */\r\n build(): T {\r\n return { ...this.query };\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Employee Query Builder\r\n// ============================================================================\r\n\r\nexport class EmployeeQueryBuilder extends QueryBuilder {\r\n /**\r\n * Filter by organization\r\n */\r\n forOrganization(organizationId: ObjectIdLike): this {\r\n return this.where('organizationId', toObjectId(organizationId));\r\n }\r\n\r\n /**\r\n * Filter by user\r\n */\r\n forUser(userId: ObjectIdLike): this {\r\n return this.where('userId', toObjectId(userId));\r\n }\r\n\r\n /**\r\n * Filter by status(es)\r\n */\r\n withStatus(...statuses: EmployeeStatus[]): this {\r\n if (statuses.length === 1) {\r\n return this.where('status', statuses[0]);\r\n }\r\n return this.whereIn('status', statuses);\r\n }\r\n\r\n /**\r\n * Filter active employees\r\n */\r\n active(): this {\r\n return this.withStatus('active');\r\n }\r\n\r\n /**\r\n * Filter employed employees (not terminated)\r\n */\r\n employed(): this {\r\n return this.whereIn('status', ['active', 'on_leave', 'suspended']);\r\n }\r\n\r\n /**\r\n * Filter terminated employees\r\n */\r\n terminated(): this {\r\n return this.withStatus('terminated');\r\n }\r\n\r\n /**\r\n * Filter by department\r\n */\r\n inDepartment(department: Department | string): this {\r\n return this.where('department', department);\r\n }\r\n\r\n /**\r\n * Filter by position\r\n */\r\n inPosition(position: string): this {\r\n return this.where('position', position);\r\n }\r\n\r\n /**\r\n * Filter by employment type\r\n */\r\n withEmploymentType(type: EmploymentType | string): this {\r\n return this.where('employmentType', type);\r\n }\r\n\r\n /**\r\n * Filter by hire date (after)\r\n */\r\n hiredAfter(date: Date): this {\r\n return this.whereGte('hireDate', date);\r\n }\r\n\r\n /**\r\n * Filter by hire date (before)\r\n */\r\n hiredBefore(date: Date): this {\r\n return this.whereLte('hireDate', date);\r\n }\r\n\r\n /**\r\n * Filter by minimum salary\r\n */\r\n withMinSalary(amount: number): this {\r\n return this.whereGte('compensation.netSalary', amount);\r\n }\r\n\r\n /**\r\n * Filter by maximum salary\r\n */\r\n withMaxSalary(amount: number): this {\r\n return this.whereLte('compensation.netSalary', amount);\r\n }\r\n\r\n /**\r\n * Filter by salary range\r\n */\r\n withSalaryRange(min: number, max: number): this {\r\n return this.whereBetween('compensation.netSalary', min, max);\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Payroll Query Builder\r\n// ============================================================================\r\n\r\nexport class PayrollQueryBuilder extends QueryBuilder {\r\n /**\r\n * Filter by organization\r\n */\r\n forOrganization(organizationId: ObjectIdLike): this {\r\n return this.where('organizationId', toObjectId(organizationId));\r\n }\r\n\r\n /**\r\n * Filter by employee\r\n */\r\n forEmployee(employeeId: ObjectIdLike): this {\r\n return this.where('employeeId', toObjectId(employeeId));\r\n }\r\n\r\n /**\r\n * Filter by period\r\n */\r\n forPeriod(month?: number, year?: number): this {\r\n if (month !== undefined) {\r\n this.where('period.month', month);\r\n }\r\n if (year !== undefined) {\r\n this.where('period.year', year);\r\n }\r\n return this;\r\n }\r\n\r\n /**\r\n * Filter by status(es)\r\n */\r\n withStatus(...statuses: PayrollStatus[]): this {\r\n if (statuses.length === 1) {\r\n return this.where('status', statuses[0]);\r\n }\r\n return this.whereIn('status', statuses);\r\n }\r\n\r\n /**\r\n * Filter paid records\r\n */\r\n paid(): this {\r\n return this.withStatus('paid');\r\n }\r\n\r\n /**\r\n * Filter pending records\r\n */\r\n pending(): this {\r\n return this.whereIn('status', ['pending', 'processing']);\r\n }\r\n\r\n /**\r\n * Filter by date range\r\n */\r\n inDateRange(start: Date, end: Date): this {\r\n return this.whereBetween('period.payDate', start, end);\r\n }\r\n\r\n /**\r\n * Filter exported records\r\n */\r\n exported(): this {\r\n return this.where('exported', true);\r\n }\r\n\r\n /**\r\n * Filter not exported records\r\n */\r\n notExported(): this {\r\n return this.where('exported', false);\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Factory Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Create employee query builder\r\n */\r\nexport function employee(): EmployeeQueryBuilder {\r\n return new EmployeeQueryBuilder();\r\n}\r\n\r\n/**\r\n * Create payroll query builder\r\n */\r\nexport function payroll(): PayrollQueryBuilder {\r\n return new PayrollQueryBuilder();\r\n}\r\n\r\n/**\r\n * Create generic query builder\r\n */\r\nexport function createQueryBuilder<T extends Record<string, unknown> = Record<string, unknown>>(\r\n initialQuery?: T\r\n): QueryBuilder<T> {\r\n return new QueryBuilder(initialQuery);\r\n}\r\n\r\n// ============================================================================\r\n// Convenience Query Builders\r\n// ============================================================================\r\n\r\n/**\r\n * Build employee query from options\r\n */\r\nexport function buildEmployeeQuery(options: {\r\n organizationId: ObjectIdLike;\r\n userId?: ObjectIdLike;\r\n statuses?: EmployeeStatus[];\r\n department?: Department | string;\r\n employmentType?: EmploymentType | string;\r\n}): Record<string, unknown> {\r\n const builder = employee().forOrganization(options.organizationId);\r\n\r\n if (options.userId) {\r\n builder.forUser(options.userId);\r\n }\r\n if (options.statuses) {\r\n builder.withStatus(...options.statuses);\r\n }\r\n if (options.department) {\r\n builder.inDepartment(options.department);\r\n }\r\n if (options.employmentType) {\r\n builder.withEmploymentType(options.employmentType);\r\n }\r\n\r\n return builder.build();\r\n}\r\n\r\n/**\r\n * Build payroll query from options\r\n */\r\nexport function buildPayrollQuery(options: {\r\n employeeId?: ObjectIdLike;\r\n organizationId?: ObjectIdLike;\r\n month?: number;\r\n year?: number;\r\n statuses?: PayrollStatus[];\r\n}): Record<string, unknown> {\r\n const builder = payroll();\r\n\r\n if (options.organizationId) {\r\n builder.forOrganization(options.organizationId);\r\n }\r\n if (options.employeeId) {\r\n builder.forEmployee(options.employeeId);\r\n }\r\n if (options.month || options.year) {\r\n builder.forPeriod(options.month, options.year);\r\n }\r\n if (options.statuses) {\r\n builder.withStatus(...options.statuses);\r\n }\r\n\r\n return builder.build();\r\n}\r\n\r\n// ============================================================================\r\n// Aggregation Pipeline Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Build aggregation pipeline from stages\r\n */\r\nexport function buildAggregationPipeline(\r\n ...stages: Array<Record<string, unknown> | undefined | null>\r\n): Record<string, unknown>[] {\r\n return stages.filter((stage): stage is Record<string, unknown> => !!stage);\r\n}\r\n\r\n/**\r\n * Match stage\r\n */\r\nexport function matchStage(query: Record<string, unknown>): Record<string, unknown> {\r\n return { $match: query };\r\n}\r\n\r\n/**\r\n * Group stage\r\n */\r\nexport function groupStage(\r\n groupBy: string | null,\r\n aggregations: Record<string, unknown>\r\n): Record<string, unknown> {\r\n return {\r\n $group: {\r\n _id: groupBy,\r\n ...aggregations,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Sort stage\r\n */\r\nexport function sortStage(sortBy: Record<string, 1 | -1>): Record<string, unknown> {\r\n return { $sort: sortBy };\r\n}\r\n\r\n/**\r\n * Limit stage\r\n */\r\nexport function limitStage(limit: number): Record<string, unknown> {\r\n return { $limit: limit };\r\n}\r\n\r\n/**\r\n * Skip stage\r\n */\r\nexport function skipStage(skip: number): Record<string, unknown> {\r\n return { $skip: skip };\r\n}\r\n\r\n/**\r\n * Project stage\r\n */\r\nexport function projectStage(fields: Record<string, unknown>): Record<string, unknown> {\r\n return { $project: fields };\r\n}\r\n\r\n/**\r\n * Lookup stage\r\n */\r\nexport function lookupStage(options: {\r\n from: string;\r\n localField: string;\r\n foreignField: string;\r\n as: string;\r\n}): Record<string, unknown> {\r\n return { $lookup: options };\r\n}\r\n\r\n/**\r\n * Unwind stage\r\n */\r\nexport function unwindStage(\r\n path: string,\r\n options: { preserveNullAndEmptyArrays?: boolean } = {}\r\n): Record<string, unknown> {\r\n return { $unwind: { path, ...options } };\r\n}\r\n\r\n// ============================================================================\r\n// Default Export\r\n// ============================================================================\r\n\r\nexport default {\r\n toObjectId,\r\n safeToObjectId,\r\n isValidObjectId,\r\n QueryBuilder,\r\n EmployeeQueryBuilder,\r\n PayrollQueryBuilder,\r\n employee,\r\n payroll,\r\n createQueryBuilder,\r\n buildEmployeeQuery,\r\n buildPayrollQuery,\r\n buildAggregationPipeline,\r\n matchStage,\r\n groupStage,\r\n sortStage,\r\n limitStage,\r\n skipStage,\r\n projectStage,\r\n lookupStage,\r\n unwindStage,\r\n};\r\n\r\n","/**\r\n * @classytic/payroll - Calculation Utilities\r\n *\r\n * Pure, functional, composable financial calculations\r\n * No side effects, highly testable\r\n */\r\n\r\nimport type {\r\n Allowance,\r\n Deduction,\r\n Compensation,\r\n TaxCalculationResult,\r\n CompensationBreakdownResult,\r\n ProRatingResult,\r\n PayPeriodInfo,\r\n} from '../types.js';\r\nimport { diffInDays } from './date.js';\r\n\r\n// ============================================================================\r\n// Basic Math Operations\r\n// ============================================================================\r\n\r\n/**\r\n * Sum array of numbers\r\n */\r\nexport function sum(numbers: number[]): number {\r\n return numbers.reduce((total, n) => total + n, 0);\r\n}\r\n\r\n/**\r\n * Sum by property\r\n */\r\nexport function sumBy<T>(items: T[], getter: (item: T) => number): number {\r\n return items.reduce((total, item) => total + getter(item), 0);\r\n}\r\n\r\n/**\r\n * Sum allowances\r\n */\r\nexport function sumAllowances(allowances: Array<{ amount: number }>): number {\r\n return sumBy(allowances, (a) => a.amount);\r\n}\r\n\r\n/**\r\n * Sum deductions\r\n */\r\nexport function sumDeductions(deductions: Array<{ amount: number }>): number {\r\n return sumBy(deductions, (d) => d.amount);\r\n}\r\n\r\n/**\r\n * Apply percentage to amount\r\n */\r\nexport function applyPercentage(amount: number, percentage: number): number {\r\n return Math.round(amount * (percentage / 100));\r\n}\r\n\r\n/**\r\n * Calculate percentage of total\r\n */\r\nexport function calculatePercentage(part: number, total: number): number {\r\n return total > 0 ? Math.round((part / total) * 100) : 0;\r\n}\r\n\r\n/**\r\n * Round to decimal places\r\n */\r\nexport function roundTo(value: number, decimals = 2): number {\r\n const factor = Math.pow(10, decimals);\r\n return Math.round(value * factor) / factor;\r\n}\r\n\r\n// ============================================================================\r\n// Salary Calculations\r\n// ============================================================================\r\n\r\n/**\r\n * Calculate gross salary from base and allowances\r\n */\r\nexport function calculateGross(\r\n baseAmount: number,\r\n allowances: Array<{ amount: number }>\r\n): number {\r\n return baseAmount + sumAllowances(allowances);\r\n}\r\n\r\n/**\r\n * Calculate net salary from gross and deductions\r\n */\r\nexport function calculateNet(\r\n gross: number,\r\n deductions: Array<{ amount: number }>\r\n): number {\r\n return Math.max(0, gross - sumDeductions(deductions));\r\n}\r\n\r\n/**\r\n * Calculate total compensation\r\n */\r\nexport function calculateTotalCompensation(\r\n baseAmount: number,\r\n allowances: Array<{ amount: number }>,\r\n deductions: Array<{ amount: number }>\r\n): { gross: number; net: number; deductions: number } {\r\n const gross = calculateGross(baseAmount, allowances);\r\n const totalDeductions = sumDeductions(deductions);\r\n const net = calculateNet(gross, deductions);\r\n return { gross, net, deductions: totalDeductions };\r\n}\r\n\r\n// ============================================================================\r\n// Allowance & Deduction Calculation\r\n// ============================================================================\r\n\r\n/**\r\n * Calculate allowance amount (handles percentage-based)\r\n */\r\nexport function calculateAllowanceAmount(\r\n allowance: Pick<Allowance, 'amount' | 'isPercentage' | 'value'>,\r\n baseAmount: number\r\n): number {\r\n if (allowance.isPercentage && allowance.value !== undefined) {\r\n return applyPercentage(baseAmount, allowance.value);\r\n }\r\n return allowance.amount;\r\n}\r\n\r\n/**\r\n * Calculate deduction amount (handles percentage-based)\r\n */\r\nexport function calculateDeductionAmount(\r\n deduction: Pick<Deduction, 'amount' | 'isPercentage' | 'value'>,\r\n baseAmount: number\r\n): number {\r\n if (deduction.isPercentage && deduction.value !== undefined) {\r\n return applyPercentage(baseAmount, deduction.value);\r\n }\r\n return deduction.amount;\r\n}\r\n\r\n/**\r\n * Calculate all allowances with their actual amounts\r\n */\r\nexport function calculateAllowances(\r\n allowances: Allowance[],\r\n baseAmount: number\r\n): Array<Allowance & { calculatedAmount: number }> {\r\n return allowances.map((allowance) => ({\r\n ...allowance,\r\n calculatedAmount: calculateAllowanceAmount(allowance, baseAmount),\r\n }));\r\n}\r\n\r\n/**\r\n * Calculate all deductions with their actual amounts\r\n */\r\nexport function calculateDeductions(\r\n deductions: Deduction[],\r\n baseAmount: number\r\n): Array<Deduction & { calculatedAmount: number }> {\r\n return deductions.map((deduction) => ({\r\n ...deduction,\r\n calculatedAmount: calculateDeductionAmount(deduction, baseAmount),\r\n }));\r\n}\r\n\r\n// ============================================================================\r\n// Compensation Breakdown\r\n// ============================================================================\r\n\r\n/**\r\n * Calculate full compensation breakdown\r\n */\r\nexport function calculateCompensationBreakdown(\r\n compensation: Pick<Compensation, 'baseAmount' | 'allowances' | 'deductions'>\r\n): CompensationBreakdownResult {\r\n const { baseAmount, allowances = [], deductions = [] } = compensation;\r\n\r\n const calculatedAllowances = calculateAllowances(allowances, baseAmount);\r\n const calculatedDeductions = calculateDeductions(deductions, baseAmount);\r\n\r\n const grossAmount =\r\n baseAmount + sumBy(calculatedAllowances, (a) => a.calculatedAmount);\r\n const netAmount =\r\n grossAmount - sumBy(calculatedDeductions, (d) => d.calculatedAmount);\r\n\r\n return {\r\n baseAmount,\r\n allowances: calculatedAllowances,\r\n deductions: calculatedDeductions,\r\n grossAmount,\r\n netAmount: Math.max(0, netAmount),\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Pro-Rating Calculations\r\n// ============================================================================\r\n\r\n/**\r\n * Calculate pro-rating for mid-month hires\r\n */\r\nexport function calculateProRating(\r\n hireDate: Date,\r\n periodStart: Date,\r\n periodEnd: Date\r\n): ProRatingResult {\r\n const totalDays = diffInDays(periodStart, periodEnd) + 1;\r\n\r\n // Hired before period start - no pro-rating\r\n if (hireDate <= periodStart) {\r\n return {\r\n isProRated: false,\r\n totalDays,\r\n actualDays: totalDays,\r\n ratio: 1,\r\n };\r\n }\r\n\r\n // Hired during the period - pro-rate\r\n if (hireDate > periodStart && hireDate <= periodEnd) {\r\n const actualDays = diffInDays(hireDate, periodEnd) + 1;\r\n const ratio = actualDays / totalDays;\r\n\r\n return {\r\n isProRated: true,\r\n totalDays,\r\n actualDays,\r\n ratio,\r\n };\r\n }\r\n\r\n // Hired after period - no work days\r\n return {\r\n isProRated: false,\r\n totalDays,\r\n actualDays: 0,\r\n ratio: 0,\r\n };\r\n}\r\n\r\n/**\r\n * Apply pro-rating to an amount\r\n */\r\nexport function applyProRating(\r\n amount: number,\r\n proRating: ProRatingResult\r\n): number {\r\n return Math.round(amount * proRating.ratio);\r\n}\r\n\r\n/**\r\n * Calculate pro-rated salary\r\n */\r\nexport function calculateProRatedSalary(\r\n baseAmount: number,\r\n hireDate: Date,\r\n period: PayPeriodInfo\r\n): { amount: number; proRating: ProRatingResult } {\r\n const proRating = calculateProRating(hireDate, period.startDate, period.endDate);\r\n const amount = applyProRating(baseAmount, proRating);\r\n return { amount, proRating };\r\n}\r\n\r\n// ============================================================================\r\n// Tax Calculations\r\n// ============================================================================\r\n\r\n/**\r\n * Apply tax brackets to calculate tax\r\n */\r\nexport function applyTaxBrackets(\r\n amount: number,\r\n brackets: Array<{ min: number; max: number; rate: number }>\r\n): number {\r\n let tax = 0;\r\n\r\n for (const bracket of brackets) {\r\n if (amount > bracket.min) {\r\n const taxableAmount = Math.min(amount, bracket.max) - bracket.min;\r\n tax += taxableAmount * bracket.rate;\r\n }\r\n }\r\n\r\n return Math.round(tax);\r\n}\r\n\r\n/**\r\n * Calculate tax with result\r\n */\r\nexport function calculateTax(\r\n amount: number,\r\n brackets: Array<{ min: number; max: number; rate: number }>\r\n): TaxCalculationResult {\r\n const tax = applyTaxBrackets(amount, brackets);\r\n return {\r\n gross: amount,\r\n tax,\r\n net: amount - tax,\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Functional Composition\r\n// ============================================================================\r\n\r\n/**\r\n * Pipe functions left-to-right\r\n * pipe(f, g, h)(x) === h(g(f(x)))\r\n */\r\nexport function pipe<T>(...fns: Array<(value: T) => T>): (value: T) => T {\r\n return (value: T) => fns.reduce((acc, fn) => fn(acc), value);\r\n}\r\n\r\n/**\r\n * Compose functions right-to-left\r\n * compose(f, g, h)(x) === f(g(h(x)))\r\n */\r\nexport function compose<T>(...fns: Array<(value: T) => T>): (value: T) => T {\r\n return (value: T) => fns.reduceRight((acc, fn) => fn(acc), value);\r\n}\r\n\r\n/**\r\n * Create an allowance calculator factory\r\n */\r\nexport function createAllowanceCalculator(\r\n allowances: Allowance[]\r\n): (baseSalary: number) => Array<Allowance & { calculatedAmount: number }> {\r\n return (baseSalary: number) => calculateAllowances(allowances, baseSalary);\r\n}\r\n\r\n/**\r\n * Create a deduction calculator factory\r\n */\r\nexport function createDeductionCalculator(\r\n deductions: Deduction[]\r\n): (baseSalary: number) => Array<Deduction & { calculatedAmount: number }> {\r\n return (baseSalary: number) => calculateDeductions(deductions, baseSalary);\r\n}\r\n\r\n// ============================================================================\r\n// Overtime Calculations\r\n// ============================================================================\r\n\r\n/**\r\n * Calculate overtime pay\r\n */\r\nexport function calculateOvertime(\r\n hourlyRate: number,\r\n overtimeHours: number,\r\n multiplier = 1.5\r\n): number {\r\n return Math.round(hourlyRate * overtimeHours * multiplier);\r\n}\r\n\r\n/**\r\n * Calculate hourly rate from monthly salary\r\n */\r\nexport function calculateHourlyRate(\r\n monthlySalary: number,\r\n hoursPerMonth = 176 // 44 hours/week * 4 weeks\r\n): number {\r\n return Math.round(monthlySalary / hoursPerMonth);\r\n}\r\n\r\n/**\r\n * Calculate daily rate from monthly salary\r\n */\r\nexport function calculateDailyRate(\r\n monthlySalary: number,\r\n daysPerMonth = 22\r\n): number {\r\n return Math.round(monthlySalary / daysPerMonth);\r\n}\r\n\r\n// ============================================================================\r\n// Default Export\r\n// ============================================================================\r\n\r\nexport default {\r\n sum,\r\n sumBy,\r\n sumAllowances,\r\n sumDeductions,\r\n applyPercentage,\r\n calculatePercentage,\r\n roundTo,\r\n calculateGross,\r\n calculateNet,\r\n calculateTotalCompensation,\r\n calculateAllowanceAmount,\r\n calculateDeductionAmount,\r\n calculateAllowances,\r\n calculateDeductions,\r\n calculateCompensationBreakdown,\r\n calculateProRating,\r\n applyProRating,\r\n calculateProRatedSalary,\r\n applyTaxBrackets,\r\n calculateTax,\r\n pipe,\r\n compose,\r\n createAllowanceCalculator,\r\n createDeductionCalculator,\r\n calculateOvertime,\r\n calculateHourlyRate,\r\n calculateDailyRate,\r\n};\r\n\r\n","/**\r\n * @classytic/payroll - Error Handling\r\n *\r\n * Custom error classes with error codes and HTTP status\r\n */\r\n\r\nimport type { ErrorCode, HttpError } from '../types.js';\r\n\r\n// ============================================================================\r\n// Base Error Class\r\n// ============================================================================\r\n\r\nexport class PayrollError extends Error implements HttpError {\r\n readonly code: ErrorCode;\r\n readonly status: number;\r\n readonly context?: Record<string, unknown>;\r\n readonly timestamp: Date;\r\n\r\n constructor(\r\n message: string,\r\n code: ErrorCode = 'PAYROLL_ERROR',\r\n status = 500,\r\n context?: Record<string, unknown>\r\n ) {\r\n super(message);\r\n this.name = 'PayrollError';\r\n this.code = code;\r\n this.status = status;\r\n this.context = context;\r\n this.timestamp = new Date();\r\n\r\n // Maintains proper stack trace for where error was thrown\r\n if (Error.captureStackTrace) {\r\n Error.captureStackTrace(this, PayrollError);\r\n }\r\n }\r\n\r\n toJSON(): Record<string, unknown> {\r\n return {\r\n name: this.name,\r\n code: this.code,\r\n message: this.message,\r\n status: this.status,\r\n context: this.context,\r\n timestamp: this.timestamp.toISOString(),\r\n };\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Specific Error Classes\r\n// ============================================================================\r\n\r\n/**\r\n * Not initialized error\r\n */\r\nexport class NotInitializedError extends PayrollError {\r\n constructor(message = 'Payroll not initialized. Call Payroll.initialize() first.') {\r\n super(message, 'NOT_INITIALIZED', 500);\r\n this.name = 'NotInitializedError';\r\n }\r\n}\r\n\r\n/**\r\n * Employee not found error\r\n */\r\nexport class EmployeeNotFoundError extends PayrollError {\r\n constructor(employeeId?: string, context?: Record<string, unknown>) {\r\n super(\r\n employeeId ? `Employee not found: ${employeeId}` : 'Employee not found',\r\n 'EMPLOYEE_NOT_FOUND',\r\n 404,\r\n context\r\n );\r\n this.name = 'EmployeeNotFoundError';\r\n }\r\n}\r\n\r\n/**\r\n * Invalid employee error\r\n */\r\nexport class InvalidEmployeeError extends PayrollError {\r\n constructor(message: string, context?: Record<string, unknown>) {\r\n super(message, 'INVALID_EMPLOYEE', 400, context);\r\n this.name = 'InvalidEmployeeError';\r\n }\r\n}\r\n\r\n/**\r\n * Duplicate payroll error\r\n */\r\nexport class DuplicatePayrollError extends PayrollError {\r\n constructor(\r\n employeeId: string,\r\n month: number,\r\n year: number,\r\n context?: Record<string, unknown>\r\n ) {\r\n super(\r\n `Payroll already processed for employee ${employeeId} in ${month}/${year}`,\r\n 'DUPLICATE_PAYROLL',\r\n 409,\r\n { employeeId, month, year, ...context }\r\n );\r\n this.name = 'DuplicatePayrollError';\r\n }\r\n}\r\n\r\n/**\r\n * Validation error\r\n */\r\nexport class ValidationError extends PayrollError {\r\n readonly errors: string[];\r\n\r\n constructor(errors: string | string[], context?: Record<string, unknown>) {\r\n const errorArray = Array.isArray(errors) ? errors : [errors];\r\n super(errorArray.join(', '), 'VALIDATION_ERROR', 400, context);\r\n this.name = 'ValidationError';\r\n this.errors = errorArray;\r\n }\r\n}\r\n\r\n/**\r\n * Employee terminated error\r\n */\r\nexport class EmployeeTerminatedError extends PayrollError {\r\n constructor(employeeId?: string, context?: Record<string, unknown>) {\r\n super(\r\n employeeId\r\n ? `Cannot perform operation on terminated employee: ${employeeId}`\r\n : 'Cannot perform operation on terminated employee',\r\n 'EMPLOYEE_TERMINATED',\r\n 400,\r\n context\r\n );\r\n this.name = 'EmployeeTerminatedError';\r\n }\r\n}\r\n\r\n/**\r\n * Already processed error\r\n */\r\nexport class AlreadyProcessedError extends PayrollError {\r\n constructor(message: string, context?: Record<string, unknown>) {\r\n super(message, 'ALREADY_PROCESSED', 409, context);\r\n this.name = 'AlreadyProcessedError';\r\n }\r\n}\r\n\r\n/**\r\n * Not eligible error\r\n */\r\nexport class NotEligibleError extends PayrollError {\r\n constructor(message: string, context?: Record<string, unknown>) {\r\n super(message, 'NOT_ELIGIBLE', 400, context);\r\n this.name = 'NotEligibleError';\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Error Factory\r\n// ============================================================================\r\n\r\n/**\r\n * Create error from code\r\n */\r\nexport function createError(\r\n code: ErrorCode,\r\n message: string,\r\n context?: Record<string, unknown>\r\n): PayrollError {\r\n const statusMap: Record<ErrorCode, number> = {\r\n PAYROLL_ERROR: 500,\r\n NOT_INITIALIZED: 500,\r\n EMPLOYEE_NOT_FOUND: 404,\r\n INVALID_EMPLOYEE: 400,\r\n DUPLICATE_PAYROLL: 409,\r\n VALIDATION_ERROR: 400,\r\n EMPLOYEE_TERMINATED: 400,\r\n ALREADY_PROCESSED: 409,\r\n NOT_ELIGIBLE: 400,\r\n };\r\n\r\n return new PayrollError(message, code, statusMap[code] || 500, context);\r\n}\r\n\r\n// ============================================================================\r\n// Type Guards\r\n// ============================================================================\r\n\r\n/**\r\n * Check if error is PayrollError\r\n */\r\nexport function isPayrollError(error: unknown): error is PayrollError {\r\n return error instanceof PayrollError;\r\n}\r\n\r\n/**\r\n * Check if error has specific code\r\n */\r\nexport function isErrorCode(error: unknown, code: ErrorCode): boolean {\r\n return isPayrollError(error) && error.code === code;\r\n}\r\n\r\n/**\r\n * Extract error info for logging\r\n */\r\nexport function extractErrorInfo(error: unknown): {\r\n message: string;\r\n code?: ErrorCode;\r\n status?: number;\r\n context?: Record<string, unknown>;\r\n} {\r\n if (isPayrollError(error)) {\r\n return {\r\n message: error.message,\r\n code: error.code,\r\n status: error.status,\r\n context: error.context,\r\n };\r\n }\r\n\r\n if (error instanceof Error) {\r\n return { message: error.message };\r\n }\r\n\r\n return { message: String(error) };\r\n}\r\n\r\n// ============================================================================\r\n// Error Handling Utilities\r\n// ============================================================================\r\n\r\n/**\r\n * Wrap async function with error handling\r\n */\r\nexport function withErrorHandling<T extends (...args: unknown[]) => Promise<unknown>>(\r\n fn: T,\r\n errorHandler?: (error: unknown) => void\r\n): T {\r\n return (async (...args: Parameters<T>) => {\r\n try {\r\n return await fn(...args);\r\n } catch (error) {\r\n if (errorHandler) {\r\n errorHandler(error);\r\n }\r\n throw error;\r\n }\r\n }) as T;\r\n}\r\n\r\n/**\r\n * Convert unknown error to PayrollError\r\n */\r\nexport function toPayrollError(error: unknown): PayrollError {\r\n if (isPayrollError(error)) {\r\n return error;\r\n }\r\n\r\n if (error instanceof Error) {\r\n return new PayrollError(error.message);\r\n }\r\n\r\n return new PayrollError(String(error));\r\n}\r\n\r\n// ============================================================================\r\n// Legacy Alias\r\n// ============================================================================\r\n\r\nexport { PayrollError as HRMError };\r\n\r\n","/**\r\n * @classytic/payroll - Main Payroll Class\r\n *\r\n * Clean, Stripe-like API for payroll management\r\n * Builder pattern for configuration\r\n */\r\n\r\nimport mongoose, { Model, ClientSession } from 'mongoose';\r\nimport type {\r\n PayrollInitConfig,\r\n HRMConfig,\r\n SingleTenantConfig,\r\n Logger,\r\n ObjectIdLike,\r\n EmployeeDocument,\r\n PayrollRecordDocument,\r\n HireEmployeeParams,\r\n UpdateEmploymentParams,\r\n TerminateEmployeeParams,\r\n ReHireEmployeeParams,\r\n ListEmployeesParams,\r\n UpdateSalaryParams,\r\n AddAllowanceParams,\r\n RemoveAllowanceParams,\r\n AddDeductionParams,\r\n RemoveDeductionParams,\r\n UpdateBankDetailsParams,\r\n ProcessSalaryParams,\r\n ProcessBulkPayrollParams,\r\n PayrollHistoryParams,\r\n PayrollSummaryParams,\r\n ExportPayrollParams,\r\n ProcessSalaryResult,\r\n BulkPayrollResult,\r\n PayrollSummaryResult,\r\n OperationContext,\r\n DeepPartial,\r\n Allowance,\r\n Deduction,\r\n TaxBracket,\r\n} from './types.js';\r\nimport { Container, type ModelsContainer, initializeContainer } from './core/container.js';\r\nimport { EventBus, createEventBus, type PayrollEventMap } from './core/events.js';\r\nimport { PluginManager, type PayrollPluginDefinition, type PluginContext } from './core/plugin.js';\r\nimport { EmployeeFactory } from './factories/employee.factory.js';\r\nimport { HRM_CONFIG, mergeConfig, TAX_BRACKETS } from './config.js';\r\nimport { HRM_TRANSACTION_CATEGORIES } from './enums.js';\r\nimport { employee as employeeQuery, payroll as payrollQuery, toObjectId } from './utils/query-builders.js';\r\nimport { getPayPeriod, diffInDays, addMonths, getWorkingDaysInMonth } from './utils/date.js';\r\nimport { calculateGross, calculateNet, sumAllowances, sumDeductions, applyTaxBrackets } from './utils/calculation.js';\r\nimport { logger as defaultLogger, getLogger, setLogger } from './utils/logger.js';\r\nimport { NotInitializedError, EmployeeNotFoundError, DuplicatePayrollError, NotEligibleError, EmployeeTerminatedError, ValidationError } from './errors/index.js';\r\n\r\n// ============================================================================\r\n// Helper: Check plugin methods exist\r\n// ============================================================================\r\n\r\nfunction hasPluginMethod(obj: unknown, method: string): boolean {\r\n return typeof obj === 'object' && obj !== null && typeof (obj as Record<string, unknown>)[method] === 'function';\r\n}\r\n\r\nfunction assertPluginMethod(obj: unknown, method: string, context: string): void {\r\n if (!hasPluginMethod(obj, method)) {\r\n throw new Error(\r\n `Method '${method}' not found on employee. Did you forget to apply employeePlugin to your Employee schema? ` +\r\n `Context: ${context}`\r\n );\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Helper: Check if date is within range\r\n// ============================================================================\r\n\r\nfunction isEffectiveForPeriod(\r\n item: { effectiveFrom?: Date | null; effectiveTo?: Date | null },\r\n periodStart: Date,\r\n periodEnd: Date\r\n): boolean {\r\n const effectiveFrom = item.effectiveFrom ? new Date(item.effectiveFrom) : new Date(0);\r\n const effectiveTo = item.effectiveTo ? new Date(item.effectiveTo) : new Date('2099-12-31');\r\n \r\n // Item is effective if its range overlaps with the period\r\n return effectiveFrom <= periodEnd && effectiveTo >= periodStart;\r\n}\r\n\r\n// ============================================================================\r\n// Payroll Class\r\n// ============================================================================\r\n\r\nexport class Payroll {\r\n private _container: Container;\r\n private _events: EventBus;\r\n private _plugins: PluginManager | null = null;\r\n private _initialized = false;\r\n\r\n constructor() {\r\n this._container = Container.getInstance();\r\n this._events = createEventBus();\r\n }\r\n\r\n // ========================================\r\n // Initialization\r\n // ========================================\r\n\r\n /**\r\n * Initialize Payroll with models and configuration\r\n */\r\n initialize(config: PayrollInitConfig): this {\r\n const { EmployeeModel, PayrollRecordModel, TransactionModel, AttendanceModel, singleTenant, logger: customLogger, config: customConfig } = config;\r\n\r\n if (!EmployeeModel || !PayrollRecordModel || !TransactionModel) {\r\n throw new Error('EmployeeModel, PayrollRecordModel, and TransactionModel are required');\r\n }\r\n\r\n if (customLogger) {\r\n setLogger(customLogger);\r\n }\r\n\r\n initializeContainer({\r\n models: {\r\n EmployeeModel,\r\n PayrollRecordModel,\r\n TransactionModel,\r\n AttendanceModel: AttendanceModel ?? null,\r\n },\r\n config: customConfig as Partial<HRMConfig>,\r\n singleTenant: singleTenant ?? null,\r\n logger: customLogger,\r\n });\r\n\r\n // Setup plugin manager\r\n const pluginContext: PluginContext = {\r\n payroll: this as unknown as import('./types.js').PayrollInstance,\r\n events: this._events,\r\n logger: getLogger(),\r\n getConfig: <T = unknown>(key: string): T | undefined => {\r\n const config = this._container.getConfig();\r\n return (config as unknown as Record<string, T>)[key];\r\n },\r\n addHook: (event, handler) => this._events.on(event, handler),\r\n };\r\n this._plugins = new PluginManager(pluginContext);\r\n\r\n this._initialized = true;\r\n\r\n getLogger().info('Payroll initialized', {\r\n hasAttendanceIntegration: !!AttendanceModel,\r\n isSingleTenant: !!singleTenant,\r\n });\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Check if initialized\r\n */\r\n isInitialized(): boolean {\r\n return this._initialized;\r\n }\r\n\r\n /**\r\n * Ensure initialized\r\n */\r\n private ensureInitialized(): void {\r\n if (!this._initialized) {\r\n throw new NotInitializedError();\r\n }\r\n }\r\n\r\n /**\r\n * Get models\r\n */\r\n private get models(): ModelsContainer {\r\n this.ensureInitialized();\r\n return this._container.getModels();\r\n }\r\n\r\n /**\r\n * Get config\r\n */\r\n private get config(): HRMConfig {\r\n return this._container.getConfig();\r\n }\r\n\r\n // ========================================\r\n // Plugin System\r\n // ========================================\r\n\r\n /**\r\n * Register a plugin\r\n */\r\n async use(plugin: PayrollPluginDefinition): Promise<this> {\r\n this.ensureInitialized();\r\n await this._plugins!.register(plugin);\r\n return this;\r\n }\r\n\r\n /**\r\n * Subscribe to events\r\n */\r\n on<K extends keyof PayrollEventMap>(\r\n event: K,\r\n handler: (payload: PayrollEventMap[K]) => void | Promise<void>\r\n ): () => void {\r\n return this._events.on(event, handler);\r\n }\r\n\r\n // ========================================\r\n // Employment Lifecycle\r\n // ========================================\r\n\r\n /**\r\n * Hire a new employee\r\n */\r\n async hire(params: HireEmployeeParams): Promise<EmployeeDocument> {\r\n this.ensureInitialized();\r\n const { userId, employment, compensation, bankDetails, context } = params;\r\n const session = context?.session;\r\n\r\n // Auto-inject organizationId in single-tenant mode\r\n const organizationId = params.organizationId ?? this._container.getOrganizationId();\r\n if (!organizationId) {\r\n throw new Error('organizationId is required (or configure single-tenant mode)');\r\n }\r\n\r\n // Check for existing active employee\r\n const existingQuery = employeeQuery()\r\n .forUser(userId)\r\n .forOrganization(organizationId)\r\n .employed()\r\n .build();\r\n\r\n let existing = this.models.EmployeeModel.findOne(existingQuery);\r\n if (session) existing = existing.session(session);\r\n \r\n if (await existing) {\r\n throw new Error('User is already an active employee in this organization');\r\n }\r\n\r\n const employeeData = EmployeeFactory.create({\r\n userId,\r\n organizationId,\r\n employment,\r\n compensation: {\r\n ...compensation,\r\n currency: compensation.currency || this.config.payroll.defaultCurrency,\r\n },\r\n bankDetails,\r\n });\r\n\r\n const [employee] = await this.models.EmployeeModel.create([employeeData], { session });\r\n\r\n // Emit event\r\n this._events.emitSync('employee:hired', {\r\n employee: {\r\n id: employee._id,\r\n employeeId: employee.employeeId,\r\n position: employee.position,\r\n department: employee.department,\r\n },\r\n organizationId: employee.organizationId,\r\n context,\r\n });\r\n\r\n getLogger().info('Employee hired', {\r\n employeeId: employee.employeeId,\r\n organizationId: organizationId.toString(),\r\n position: employment.position,\r\n });\r\n\r\n return employee;\r\n }\r\n\r\n /**\r\n * Update employment details\r\n * NOTE: Status changes to 'terminated' must use terminate() method\r\n */\r\n async updateEmployment(params: UpdateEmploymentParams): Promise<EmployeeDocument> {\r\n this.ensureInitialized();\r\n const { employeeId, updates, context } = params;\r\n const session = context?.session;\r\n\r\n let query = this.models.EmployeeModel.findById(toObjectId(employeeId));\r\n if (session) query = query.session(session);\r\n \r\n const employee = await query;\r\n if (!employee) {\r\n throw new EmployeeNotFoundError(employeeId.toString());\r\n }\r\n\r\n if (employee.status === 'terminated') {\r\n throw new EmployeeTerminatedError(employee.employeeId);\r\n }\r\n\r\n // IMPORTANT: Block direct status change to 'terminated' - must use terminate()\r\n if (updates.status === 'terminated') {\r\n throw new ValidationError(\r\n 'Cannot set status to terminated directly. Use the terminate() method instead to ensure proper history tracking.',\r\n { field: 'status' }\r\n );\r\n }\r\n\r\n const allowedUpdates = ['department', 'position', 'employmentType', 'status', 'workSchedule'];\r\n for (const [key, value] of Object.entries(updates)) {\r\n if (allowedUpdates.includes(key)) {\r\n (employee as Record<string, unknown>)[key] = value;\r\n }\r\n }\r\n\r\n await employee.save({ session });\r\n\r\n getLogger().info('Employee updated', {\r\n employeeId: employee.employeeId,\r\n updates: Object.keys(updates),\r\n });\r\n\r\n return employee;\r\n }\r\n\r\n /**\r\n * Terminate employee\r\n */\r\n async terminate(params: TerminateEmployeeParams): Promise<EmployeeDocument> {\r\n this.ensureInitialized();\r\n const { employeeId, terminationDate = new Date(), reason = 'resignation', notes, context } = params;\r\n const session = context?.session;\r\n\r\n let query = this.models.EmployeeModel.findById(toObjectId(employeeId));\r\n if (session) query = query.session(session);\r\n \r\n const employee = await query;\r\n if (!employee) {\r\n throw new EmployeeNotFoundError(employeeId.toString());\r\n }\r\n\r\n // Check plugin method exists\r\n assertPluginMethod(employee, 'terminate', 'terminate()');\r\n\r\n (employee as unknown as { terminate: (reason: string, date: Date) => void }).terminate(reason, terminationDate);\r\n\r\n if (notes) {\r\n employee.notes = (employee.notes || '') + `\\nTermination: ${notes}`;\r\n }\r\n\r\n await employee.save({ session });\r\n\r\n // Emit event\r\n this._events.emitSync('employee:terminated', {\r\n employee: {\r\n id: employee._id,\r\n employeeId: employee.employeeId,\r\n },\r\n terminationDate,\r\n reason,\r\n organizationId: employee.organizationId,\r\n context,\r\n });\r\n\r\n getLogger().info('Employee terminated', {\r\n employeeId: employee.employeeId,\r\n reason,\r\n });\r\n\r\n return employee;\r\n }\r\n\r\n /**\r\n * Re-hire terminated employee\r\n */\r\n async reHire(params: ReHireEmployeeParams): Promise<EmployeeDocument> {\r\n this.ensureInitialized();\r\n const { employeeId, hireDate = new Date(), position, department, compensation, context } = params;\r\n const session = context?.session;\r\n\r\n if (!this.config.employment.allowReHiring) {\r\n throw new Error('Re-hiring is not enabled');\r\n }\r\n\r\n let query = this.models.EmployeeModel.findById(toObjectId(employeeId));\r\n if (session) query = query.session(session);\r\n \r\n const employee = await query;\r\n if (!employee) {\r\n throw new EmployeeNotFoundError(employeeId.toString());\r\n }\r\n\r\n // Check plugin method exists\r\n assertPluginMethod(employee, 'reHire', 'reHire()');\r\n\r\n (employee as unknown as { reHire: (date: Date, position?: string, department?: string) => void }).reHire(hireDate, position, department);\r\n\r\n if (compensation) {\r\n employee.compensation = { ...employee.compensation, ...compensation } as typeof employee.compensation;\r\n }\r\n\r\n await employee.save({ session });\r\n\r\n // Emit event\r\n this._events.emitSync('employee:rehired', {\r\n employee: {\r\n id: employee._id,\r\n employeeId: employee.employeeId,\r\n position: employee.position,\r\n },\r\n organizationId: employee.organizationId,\r\n context,\r\n });\r\n\r\n getLogger().info('Employee re-hired', {\r\n employeeId: employee.employeeId,\r\n });\r\n\r\n return employee;\r\n }\r\n\r\n /**\r\n * Get employee by ID\r\n */\r\n async getEmployee(params: {\r\n employeeId: ObjectIdLike;\r\n populateUser?: boolean;\r\n session?: ClientSession;\r\n }): Promise<EmployeeDocument> {\r\n this.ensureInitialized();\r\n const { employeeId, populateUser = true, session } = params;\r\n\r\n let query = this.models.EmployeeModel.findById(toObjectId(employeeId));\r\n if (session) query = query.session(session);\r\n if (populateUser) query = query.populate('userId', 'name email phone');\r\n\r\n const employee = await query;\r\n if (!employee) {\r\n throw new EmployeeNotFoundError(employeeId.toString());\r\n }\r\n\r\n return employee;\r\n }\r\n\r\n /**\r\n * List employees\r\n */\r\n async listEmployees(params: ListEmployeesParams): Promise<{\r\n docs: EmployeeDocument[];\r\n totalDocs: number;\r\n page: number;\r\n limit: number;\r\n }> {\r\n this.ensureInitialized();\r\n const { organizationId, filters = {}, pagination = {} } = params;\r\n\r\n let queryBuilder = employeeQuery().forOrganization(organizationId);\r\n\r\n if (filters.status) queryBuilder = queryBuilder.withStatus(filters.status);\r\n if (filters.department) queryBuilder = queryBuilder.inDepartment(filters.department);\r\n if (filters.employmentType) queryBuilder = queryBuilder.withEmploymentType(filters.employmentType);\r\n if (filters.minSalary) queryBuilder = queryBuilder.withMinSalary(filters.minSalary);\r\n if (filters.maxSalary) queryBuilder = queryBuilder.withMaxSalary(filters.maxSalary);\r\n\r\n const query = queryBuilder.build();\r\n const page = pagination.page || 1;\r\n const limit = pagination.limit || 20;\r\n const sort = pagination.sort || { createdAt: -1 };\r\n\r\n const [docs, totalDocs] = await Promise.all([\r\n this.models.EmployeeModel.find(query)\r\n .populate('userId', 'name email phone')\r\n .sort(sort)\r\n .skip((page - 1) * limit)\r\n .limit(limit),\r\n this.models.EmployeeModel.countDocuments(query),\r\n ]);\r\n\r\n return { docs, totalDocs, page, limit };\r\n }\r\n\r\n // ========================================\r\n // Compensation Management\r\n // ========================================\r\n\r\n /**\r\n * Update employee salary\r\n */\r\n async updateSalary(params: UpdateSalaryParams): Promise<EmployeeDocument> {\r\n this.ensureInitialized();\r\n const { employeeId, compensation, effectiveFrom = new Date(), context } = params;\r\n const session = context?.session;\r\n\r\n let query = this.models.EmployeeModel.findById(toObjectId(employeeId));\r\n if (session) query = query.session(session);\r\n \r\n const employee = await query;\r\n if (!employee) {\r\n throw new EmployeeNotFoundError(employeeId.toString());\r\n }\r\n\r\n if (employee.status === 'terminated') {\r\n throw new EmployeeTerminatedError(employee.employeeId);\r\n }\r\n\r\n const oldSalary = employee.compensation.netSalary;\r\n\r\n if (compensation.baseAmount !== undefined) {\r\n employee.compensation.baseAmount = compensation.baseAmount;\r\n }\r\n if (compensation.frequency) {\r\n employee.compensation.frequency = compensation.frequency;\r\n }\r\n if (compensation.currency) {\r\n employee.compensation.currency = compensation.currency;\r\n }\r\n\r\n employee.compensation.effectiveFrom = effectiveFrom;\r\n \r\n // Check plugin method exists before calling\r\n if (hasPluginMethod(employee, 'updateSalaryCalculations')) {\r\n (employee as unknown as { updateSalaryCalculations: () => void }).updateSalaryCalculations();\r\n }\r\n\r\n await employee.save({ session });\r\n\r\n // Emit event\r\n this._events.emitSync('salary:updated', {\r\n employee: { id: employee._id, employeeId: employee.employeeId },\r\n previousSalary: oldSalary || 0,\r\n newSalary: employee.compensation.netSalary || 0,\r\n effectiveFrom,\r\n organizationId: employee.organizationId,\r\n context,\r\n });\r\n\r\n getLogger().info('Salary updated', {\r\n employeeId: employee.employeeId,\r\n oldSalary,\r\n newSalary: employee.compensation.netSalary,\r\n });\r\n\r\n return employee;\r\n }\r\n\r\n /**\r\n * Add allowance to employee\r\n */\r\n async addAllowance(params: AddAllowanceParams): Promise<EmployeeDocument> {\r\n this.ensureInitialized();\r\n const { employeeId, type, amount, taxable = true, recurring = true, effectiveFrom = new Date(), effectiveTo, context } = params;\r\n const session = context?.session;\r\n\r\n let query = this.models.EmployeeModel.findById(toObjectId(employeeId));\r\n if (session) query = query.session(session);\r\n \r\n const employee = await query;\r\n if (!employee) {\r\n throw new EmployeeNotFoundError(employeeId.toString());\r\n }\r\n\r\n if (employee.status === 'terminated') {\r\n throw new EmployeeTerminatedError(employee.employeeId);\r\n }\r\n\r\n if (!employee.compensation.allowances) {\r\n employee.compensation.allowances = [];\r\n }\r\n\r\n employee.compensation.allowances.push({\r\n type,\r\n name: type,\r\n amount,\r\n taxable,\r\n recurring,\r\n effectiveFrom,\r\n effectiveTo,\r\n });\r\n\r\n if (hasPluginMethod(employee, 'updateSalaryCalculations')) {\r\n (employee as unknown as { updateSalaryCalculations: () => void }).updateSalaryCalculations();\r\n }\r\n await employee.save({ session });\r\n\r\n getLogger().info('Allowance added', {\r\n employeeId: employee.employeeId,\r\n type,\r\n amount,\r\n });\r\n\r\n return employee;\r\n }\r\n\r\n /**\r\n * Remove allowance from employee\r\n */\r\n async removeAllowance(params: RemoveAllowanceParams): Promise<EmployeeDocument> {\r\n this.ensureInitialized();\r\n const { employeeId, type, context } = params;\r\n const session = context?.session;\r\n\r\n let query = this.models.EmployeeModel.findById(toObjectId(employeeId));\r\n if (session) query = query.session(session);\r\n \r\n const employee = await query;\r\n if (!employee) {\r\n throw new EmployeeNotFoundError(employeeId.toString());\r\n }\r\n\r\n const before = employee.compensation.allowances?.length || 0;\r\n \r\n if (hasPluginMethod(employee, 'removeAllowance')) {\r\n (employee as unknown as { removeAllowance: (type: string) => void }).removeAllowance(type);\r\n } else {\r\n // Fallback if plugin not applied\r\n if (employee.compensation.allowances) {\r\n employee.compensation.allowances = employee.compensation.allowances.filter(\r\n (a: Allowance) => a.type !== type\r\n );\r\n }\r\n }\r\n \r\n const after = employee.compensation.allowances?.length || 0;\r\n\r\n if (before === after) {\r\n throw new Error(`Allowance type '${type}' not found`);\r\n }\r\n\r\n await employee.save({ session });\r\n\r\n getLogger().info('Allowance removed', {\r\n employeeId: employee.employeeId,\r\n type,\r\n });\r\n\r\n return employee;\r\n }\r\n\r\n /**\r\n * Add deduction to employee\r\n */\r\n async addDeduction(params: AddDeductionParams): Promise<EmployeeDocument> {\r\n this.ensureInitialized();\r\n const { employeeId, type, amount, auto = false, recurring = true, description, effectiveFrom = new Date(), effectiveTo, context } = params;\r\n const session = context?.session;\r\n\r\n let query = this.models.EmployeeModel.findById(toObjectId(employeeId));\r\n if (session) query = query.session(session);\r\n \r\n const employee = await query;\r\n if (!employee) {\r\n throw new EmployeeNotFoundError(employeeId.toString());\r\n }\r\n\r\n if (employee.status === 'terminated') {\r\n throw new EmployeeTerminatedError(employee.employeeId);\r\n }\r\n\r\n if (!employee.compensation.deductions) {\r\n employee.compensation.deductions = [];\r\n }\r\n\r\n employee.compensation.deductions.push({\r\n type,\r\n name: type,\r\n amount,\r\n auto,\r\n recurring,\r\n description,\r\n effectiveFrom,\r\n effectiveTo,\r\n });\r\n\r\n if (hasPluginMethod(employee, 'updateSalaryCalculations')) {\r\n (employee as unknown as { updateSalaryCalculations: () => void }).updateSalaryCalculations();\r\n }\r\n await employee.save({ session });\r\n\r\n getLogger().info('Deduction added', {\r\n employeeId: employee.employeeId,\r\n type,\r\n amount,\r\n auto,\r\n });\r\n\r\n return employee;\r\n }\r\n\r\n /**\r\n * Remove deduction from employee\r\n */\r\n async removeDeduction(params: RemoveDeductionParams): Promise<EmployeeDocument> {\r\n this.ensureInitialized();\r\n const { employeeId, type, context } = params;\r\n const session = context?.session;\r\n\r\n let query = this.models.EmployeeModel.findById(toObjectId(employeeId));\r\n if (session) query = query.session(session);\r\n \r\n const employee = await query;\r\n if (!employee) {\r\n throw new EmployeeNotFoundError(employeeId.toString());\r\n }\r\n\r\n const before = employee.compensation.deductions?.length || 0;\r\n \r\n if (hasPluginMethod(employee, 'removeDeduction')) {\r\n (employee as unknown as { removeDeduction: (type: string) => void }).removeDeduction(type);\r\n } else {\r\n // Fallback if plugin not applied\r\n if (employee.compensation.deductions) {\r\n employee.compensation.deductions = employee.compensation.deductions.filter(\r\n (d: Deduction) => d.type !== type\r\n );\r\n }\r\n }\r\n \r\n const after = employee.compensation.deductions?.length || 0;\r\n\r\n if (before === after) {\r\n throw new Error(`Deduction type '${type}' not found`);\r\n }\r\n\r\n await employee.save({ session });\r\n\r\n getLogger().info('Deduction removed', {\r\n employeeId: employee.employeeId,\r\n type,\r\n });\r\n\r\n return employee;\r\n }\r\n\r\n /**\r\n * Update bank details\r\n */\r\n async updateBankDetails(params: UpdateBankDetailsParams): Promise<EmployeeDocument> {\r\n this.ensureInitialized();\r\n const { employeeId, bankDetails, context } = params;\r\n const session = context?.session;\r\n\r\n let query = this.models.EmployeeModel.findById(toObjectId(employeeId));\r\n if (session) query = query.session(session);\r\n \r\n const employee = await query;\r\n if (!employee) {\r\n throw new EmployeeNotFoundError(employeeId.toString());\r\n }\r\n\r\n employee.bankDetails = { ...employee.bankDetails, ...bankDetails };\r\n await employee.save({ session });\r\n\r\n getLogger().info('Bank details updated', {\r\n employeeId: employee.employeeId,\r\n });\r\n\r\n return employee;\r\n }\r\n\r\n // ========================================\r\n // Payroll Processing\r\n // ========================================\r\n\r\n /**\r\n * Process salary for single employee\r\n * \r\n * ATOMICITY: This method creates its own transaction if none provided.\r\n * All database operations (PayrollRecord, Transaction, Employee stats) \r\n * are atomic - either all succeed or all fail.\r\n */\r\n async processSalary(params: ProcessSalaryParams): Promise<ProcessSalaryResult> {\r\n this.ensureInitialized();\r\n const { employeeId, month, year, paymentDate = new Date(), paymentMethod = 'bank', context } = params;\r\n\r\n // CRITICAL: Use provided session OR create a new transaction\r\n const providedSession = context?.session;\r\n const session = providedSession || await mongoose.startSession();\r\n const shouldManageTransaction = !providedSession && session != null;\r\n\r\n try {\r\n if (shouldManageTransaction) {\r\n await session.startTransaction();\r\n }\r\n\r\n let query = this.models.EmployeeModel.findById(toObjectId(employeeId)).populate('userId', 'name email');\r\n if (session) query = query.session(session);\r\n \r\n const employee = await query;\r\n if (!employee) {\r\n throw new EmployeeNotFoundError(employeeId.toString());\r\n }\r\n\r\n // Check eligibility - with plugin method verification\r\n const canReceive = hasPluginMethod(employee, 'canReceiveSalary')\r\n ? (employee as unknown as { canReceiveSalary: () => boolean }).canReceiveSalary()\r\n : (employee.status === 'active' && (employee.compensation?.baseAmount || 0) > 0);\r\n\r\n if (!canReceive) {\r\n throw new NotEligibleError('Employee is not eligible to receive salary');\r\n }\r\n\r\n // Check for existing payroll\r\n const existingQuery = payrollQuery()\r\n .forEmployee(employeeId)\r\n .forPeriod(month, year)\r\n .whereIn('status', ['paid', 'processing'])\r\n .build();\r\n\r\n let existingRecordQuery = this.models.PayrollRecordModel.findOne(existingQuery);\r\n if (session) existingRecordQuery = existingRecordQuery.session(session);\r\n const existingRecord = await existingRecordQuery;\r\n \r\n if (existingRecord) {\r\n throw new DuplicatePayrollError(employee.employeeId, month, year);\r\n }\r\n\r\n const period = { ...getPayPeriod(month, year), payDate: paymentDate };\r\n const breakdown = await this.calculateSalaryBreakdown(employee, period, session);\r\n\r\n // Handle userId - could be ObjectId, populated doc, or null\r\n const userIdValue = employee.userId\r\n ? (typeof employee.userId === 'object' && '_id' in employee.userId\r\n ? (employee.userId as { _id: mongoose.Types.ObjectId })._id\r\n : employee.userId)\r\n : undefined;\r\n\r\n const [payrollRecord] = await this.models.PayrollRecordModel.create([{\r\n organizationId: employee.organizationId,\r\n employeeId: employee._id,\r\n userId: userIdValue,\r\n period,\r\n breakdown,\r\n status: 'processing',\r\n paymentMethod,\r\n processedAt: new Date(),\r\n processedBy: context?.userId ? toObjectId(context.userId) : undefined,\r\n }], session ? { session } : {});\r\n\r\n const [transaction] = await this.models.TransactionModel.create([{\r\n organizationId: employee.organizationId,\r\n type: 'expense',\r\n category: HRM_TRANSACTION_CATEGORIES.SALARY,\r\n amount: breakdown.netSalary,\r\n method: paymentMethod,\r\n status: 'completed',\r\n date: paymentDate,\r\n referenceId: employee._id,\r\n referenceModel: 'Employee',\r\n handledBy: context?.userId ? toObjectId(context.userId) : undefined,\r\n notes: `Salary payment - ${(employee.userId as { name?: string })?.name || employee.employeeId} (${month}/${year})`,\r\n metadata: {\r\n employeeId: employee.employeeId,\r\n payrollRecordId: payrollRecord._id,\r\n period: { month, year },\r\n breakdown: {\r\n base: breakdown.baseAmount,\r\n allowances: sumAllowances(breakdown.allowances),\r\n deductions: sumDeductions(breakdown.deductions),\r\n tax: breakdown.taxAmount || 0,\r\n gross: breakdown.grossSalary,\r\n net: breakdown.netSalary,\r\n },\r\n },\r\n }], session ? { session } : {});\r\n\r\n // Update payroll record with transaction reference\r\n payrollRecord.transactionId = transaction._id;\r\n payrollRecord.status = 'paid';\r\n payrollRecord.paidAt = paymentDate;\r\n await payrollRecord.save(session ? { session } : {});\r\n\r\n // Update employee payroll stats\r\n await this.updatePayrollStats(employee, breakdown.netSalary, paymentDate, session);\r\n\r\n // Commit transaction if we created it\r\n if (shouldManageTransaction) {\r\n await session.commitTransaction();\r\n }\r\n\r\n // Emit event (after commit to ensure data is persisted)\r\n this._events.emitSync('salary:processed', {\r\n employee: {\r\n id: employee._id,\r\n employeeId: employee.employeeId,\r\n name: (employee.userId as { name?: string })?.name,\r\n },\r\n payroll: {\r\n id: payrollRecord._id,\r\n period: { month, year },\r\n grossAmount: breakdown.grossSalary,\r\n netAmount: breakdown.netSalary,\r\n },\r\n transactionId: transaction._id,\r\n organizationId: employee.organizationId,\r\n context,\r\n });\r\n\r\n getLogger().info('Salary processed', {\r\n employeeId: employee.employeeId,\r\n month,\r\n year,\r\n amount: breakdown.netSalary,\r\n });\r\n\r\n return { payrollRecord, transaction, employee };\r\n\r\n } catch (error) {\r\n // Rollback transaction if we created it\r\n if (shouldManageTransaction && session?.inTransaction()) {\r\n await session.abortTransaction();\r\n }\r\n throw error;\r\n } finally {\r\n // End session if we created it\r\n if (shouldManageTransaction && session) {\r\n await session.endSession();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Process bulk payroll\r\n * \r\n * ATOMICITY STRATEGY: Each employee is processed in its own transaction.\r\n * This allows partial success - some employees can succeed while others fail.\r\n * Failed employees don't affect successful ones.\r\n */\r\n async processBulkPayroll(params: ProcessBulkPayrollParams): Promise<BulkPayrollResult> {\r\n this.ensureInitialized();\r\n const { organizationId, month, year, employeeIds = [], paymentDate = new Date(), paymentMethod = 'bank', context } = params;\r\n\r\n const query: Record<string, unknown> = { organizationId: toObjectId(organizationId), status: 'active' };\r\n if (employeeIds.length > 0) {\r\n query._id = { $in: employeeIds.map(toObjectId) };\r\n }\r\n\r\n const employees = await this.models.EmployeeModel.find(query);\r\n\r\n const results: BulkPayrollResult = {\r\n successful: [],\r\n failed: [],\r\n total: employees.length,\r\n };\r\n\r\n // Process each employee in its own transaction for isolation\r\n for (const employee of employees) {\r\n try {\r\n // Each processSalary call manages its own transaction\r\n const result = await this.processSalary({\r\n employeeId: employee._id,\r\n month,\r\n year,\r\n paymentDate,\r\n paymentMethod,\r\n context: { ...context, session: undefined }, // Don't pass session - let processSalary create its own\r\n });\r\n\r\n results.successful.push({\r\n employeeId: employee.employeeId,\r\n amount: result.payrollRecord.breakdown.netSalary,\r\n transactionId: result.transaction._id,\r\n });\r\n } catch (error) {\r\n results.failed.push({\r\n employeeId: employee.employeeId,\r\n error: (error as Error).message,\r\n });\r\n\r\n getLogger().error('Failed to process salary', {\r\n employeeId: employee.employeeId,\r\n error: (error as Error).message,\r\n });\r\n }\r\n }\r\n\r\n // Emit completed event\r\n this._events.emitSync('payroll:completed', {\r\n organizationId: toObjectId(organizationId),\r\n period: { month, year },\r\n summary: {\r\n total: results.total,\r\n successful: results.successful.length,\r\n failed: results.failed.length,\r\n totalAmount: results.successful.reduce((sum, r) => sum + r.amount, 0),\r\n },\r\n context,\r\n });\r\n\r\n getLogger().info('Bulk payroll processed', {\r\n organizationId: organizationId.toString(),\r\n month,\r\n year,\r\n total: results.total,\r\n successful: results.successful.length,\r\n failed: results.failed.length,\r\n });\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * Get payroll history\r\n */\r\n async payrollHistory(params: PayrollHistoryParams): Promise<PayrollRecordDocument[]> {\r\n this.ensureInitialized();\r\n const { employeeId, organizationId, month, year, status, pagination = {} } = params;\r\n\r\n let queryBuilder = payrollQuery();\r\n if (employeeId) queryBuilder = queryBuilder.forEmployee(employeeId);\r\n if (organizationId) queryBuilder = queryBuilder.forOrganization(organizationId);\r\n if (month || year) queryBuilder = queryBuilder.forPeriod(month, year);\r\n if (status) queryBuilder = queryBuilder.withStatus(status);\r\n\r\n const query = queryBuilder.build();\r\n const page = pagination.page || 1;\r\n const limit = pagination.limit || 20;\r\n const sort = pagination.sort || { 'period.year': -1, 'period.month': -1 };\r\n\r\n return this.models.PayrollRecordModel.find(query)\r\n .populate('employeeId', 'employeeId position department')\r\n .populate('userId', 'name email')\r\n .populate('transactionId', 'amount method status date')\r\n .sort(sort)\r\n .skip((page - 1) * limit)\r\n .limit(limit);\r\n }\r\n\r\n /**\r\n * Get payroll summary\r\n */\r\n async payrollSummary(params: PayrollSummaryParams): Promise<PayrollSummaryResult> {\r\n this.ensureInitialized();\r\n const { organizationId, month, year } = params;\r\n\r\n const query: Record<string, unknown> = { organizationId: toObjectId(organizationId) };\r\n if (month) query['period.month'] = month;\r\n if (year) query['period.year'] = year;\r\n\r\n const [summary] = await this.models.PayrollRecordModel.aggregate([\r\n { $match: query },\r\n {\r\n $group: {\r\n _id: null,\r\n totalGross: { $sum: '$breakdown.grossSalary' },\r\n totalNet: { $sum: '$breakdown.netSalary' },\r\n totalDeductions: { $sum: { $sum: '$breakdown.deductions.amount' } },\r\n totalTax: { $sum: { $ifNull: ['$breakdown.taxAmount', 0] } },\r\n employeeCount: { $sum: 1 },\r\n paidCount: { $sum: { $cond: [{ $eq: ['$status', 'paid'] }, 1, 0] } },\r\n pendingCount: { $sum: { $cond: [{ $eq: ['$status', 'pending'] }, 1, 0] } },\r\n },\r\n },\r\n ]);\r\n\r\n return summary || {\r\n totalGross: 0,\r\n totalNet: 0,\r\n totalDeductions: 0,\r\n totalTax: 0,\r\n employeeCount: 0,\r\n paidCount: 0,\r\n pendingCount: 0,\r\n };\r\n }\r\n\r\n /**\r\n * Export payroll data\r\n */\r\n async exportPayroll(params: ExportPayrollParams): Promise<PayrollRecordDocument[]> {\r\n this.ensureInitialized();\r\n const { organizationId, startDate, endDate } = params;\r\n\r\n const query = {\r\n organizationId: toObjectId(organizationId),\r\n 'period.payDate': { $gte: startDate, $lte: endDate },\r\n };\r\n\r\n const records = await this.models.PayrollRecordModel.find(query)\r\n .populate('employeeId', 'employeeId position department')\r\n .populate('userId', 'name email')\r\n .populate('transactionId', 'amount method status date')\r\n .sort({ 'period.year': -1, 'period.month': -1 });\r\n\r\n // Mark as exported\r\n await this.models.PayrollRecordModel.updateMany(query, {\r\n exported: true,\r\n exportedAt: new Date(),\r\n });\r\n\r\n // Emit event\r\n this._events.emitSync('payroll:exported', {\r\n organizationId: toObjectId(organizationId),\r\n dateRange: { start: startDate, end: endDate },\r\n recordCount: records.length,\r\n format: 'json',\r\n });\r\n\r\n getLogger().info('Payroll data exported', {\r\n organizationId: organizationId.toString(),\r\n count: records.length,\r\n });\r\n\r\n return records;\r\n }\r\n\r\n // ========================================\r\n // Helper Methods\r\n // ========================================\r\n\r\n /**\r\n * Calculate salary breakdown with proper handling for:\r\n * - Effective dates on allowances/deductions\r\n * - Pro-rating for mid-period hires AND terminations\r\n * - Tax calculation\r\n * - Working days vs calendar days for attendance\r\n */\r\n private async calculateSalaryBreakdown(\r\n employee: EmployeeDocument,\r\n period: { month: number; year: number; startDate: Date; endDate: Date; payDate: Date },\r\n session?: ClientSession\r\n ): Promise<import('./types.js').PayrollBreakdown> {\r\n const comp = employee.compensation;\r\n let baseAmount = comp.baseAmount;\r\n\r\n // Calculate working days in the period (excluding weekends)\r\n const workingDaysInMonth = getWorkingDaysInMonth(period.year, period.month);\r\n \r\n // Pro-rating calculation considering both hire date AND termination date\r\n const proRating = this.calculateProRatingAdvanced(\r\n employee.hireDate,\r\n employee.terminationDate || null,\r\n period.startDate,\r\n period.endDate,\r\n workingDaysInMonth\r\n );\r\n\r\n if (proRating.isProRated && this.config.payroll.allowProRating) {\r\n baseAmount = Math.round(baseAmount * proRating.ratio);\r\n }\r\n\r\n // Filter allowances by effective date\r\n const effectiveAllowances = (comp.allowances || [])\r\n .filter((a) => isEffectiveForPeriod(a, period.startDate, period.endDate))\r\n .filter((a) => a.recurring !== false);\r\n\r\n // Filter deductions by effective date\r\n const effectiveDeductions = (comp.deductions || [])\r\n .filter((d) => isEffectiveForPeriod(d, period.startDate, period.endDate))\r\n .filter((d) => d.auto || d.recurring);\r\n\r\n // Apply pro-rating to allowances if needed\r\n const allowances = effectiveAllowances.map((a) => ({\r\n type: a.type,\r\n amount: proRating.isProRated && this.config.payroll.allowProRating\r\n ? Math.round(a.amount * proRating.ratio)\r\n : a.amount,\r\n taxable: a.taxable ?? true,\r\n }));\r\n\r\n // Apply pro-rating to deductions if needed\r\n const deductions = effectiveDeductions.map((d) => ({\r\n type: d.type,\r\n amount: proRating.isProRated && this.config.payroll.allowProRating\r\n ? Math.round(d.amount * proRating.ratio)\r\n : d.amount,\r\n description: d.description,\r\n }));\r\n\r\n // Attendance deduction calculation (uses working days, not calendar days)\r\n let attendanceDeduction = 0;\r\n if (this.models.AttendanceModel && this.config.payroll.attendanceIntegration) {\r\n attendanceDeduction = await this.calculateAttendanceDeduction(\r\n employee._id,\r\n employee.organizationId,\r\n period,\r\n baseAmount / proRating.workingDays, // Daily rate based on working days\r\n proRating.workingDays,\r\n session\r\n );\r\n }\r\n\r\n if (attendanceDeduction > 0) {\r\n deductions.push({\r\n type: 'absence',\r\n amount: attendanceDeduction,\r\n description: 'Unpaid leave deduction',\r\n });\r\n }\r\n\r\n // Calculate gross salary\r\n const grossSalary = calculateGross(baseAmount, allowances);\r\n \r\n // Calculate taxable amount (only taxable allowances)\r\n const taxableAllowances = allowances.filter(a => a.taxable);\r\n const taxableAmount = baseAmount + sumAllowances(taxableAllowances);\r\n \r\n // Calculate tax\r\n let taxAmount = 0;\r\n const currency = comp.currency || this.config.payroll.defaultCurrency;\r\n const taxBrackets = TAX_BRACKETS[currency] || [];\r\n \r\n if (taxBrackets.length > 0 && this.config.payroll.autoDeductions) {\r\n // Annualize the taxable amount for tax bracket calculation\r\n const annualTaxable = taxableAmount * 12;\r\n const annualTax = applyTaxBrackets(annualTaxable, taxBrackets);\r\n taxAmount = Math.round(annualTax / 12); // Monthly tax\r\n }\r\n\r\n // Add tax to deductions if applicable\r\n if (taxAmount > 0) {\r\n deductions.push({\r\n type: 'tax',\r\n amount: taxAmount,\r\n description: 'Income tax',\r\n });\r\n }\r\n\r\n // Calculate net salary\r\n const netSalary = calculateNet(grossSalary, deductions);\r\n\r\n return {\r\n baseAmount,\r\n allowances,\r\n deductions,\r\n grossSalary,\r\n netSalary,\r\n taxableAmount,\r\n taxAmount,\r\n workingDays: proRating.workingDays,\r\n actualDays: proRating.actualDays,\r\n proRatedAmount: proRating.isProRated ? baseAmount : 0,\r\n attendanceDeduction,\r\n };\r\n }\r\n\r\n /**\r\n * Advanced pro-rating calculation that handles:\r\n * - Mid-period hires\r\n * - Mid-period terminations\r\n * - Working days (not calendar days)\r\n */\r\n private calculateProRatingAdvanced(\r\n hireDate: Date,\r\n terminationDate: Date | null,\r\n periodStart: Date,\r\n periodEnd: Date,\r\n workingDaysInMonth: number\r\n ): {\r\n isProRated: boolean;\r\n ratio: number;\r\n workingDays: number;\r\n actualDays: number;\r\n } {\r\n const hire = new Date(hireDate);\r\n const termination = terminationDate ? new Date(terminationDate) : null;\r\n \r\n // Determine the actual start and end dates for this employee in this period\r\n const effectiveStart = hire > periodStart ? hire : periodStart;\r\n const effectiveEnd = termination && termination < periodEnd ? termination : periodEnd;\r\n \r\n // If employee wasn't active during this period\r\n if (effectiveStart > periodEnd || (termination && termination < periodStart)) {\r\n return {\r\n isProRated: true,\r\n ratio: 0,\r\n workingDays: workingDaysInMonth,\r\n actualDays: 0,\r\n };\r\n }\r\n \r\n // Calculate working days in the effective period\r\n const totalDays = diffInDays(periodStart, periodEnd) + 1;\r\n const actualDays = diffInDays(effectiveStart, effectiveEnd) + 1;\r\n \r\n // For working days calculation, we use a simple ratio\r\n // A more accurate implementation would count actual working days\r\n const ratio = actualDays / totalDays;\r\n const actualWorkingDays = Math.round(workingDaysInMonth * ratio);\r\n \r\n const isProRated = hire > periodStart || (termination !== null && termination < periodEnd);\r\n\r\n return {\r\n isProRated,\r\n ratio,\r\n workingDays: workingDaysInMonth,\r\n actualDays: actualWorkingDays,\r\n };\r\n }\r\n\r\n /**\r\n * Calculate attendance deduction using working days (not calendar days)\r\n */\r\n private async calculateAttendanceDeduction(\r\n employeeId: mongoose.Types.ObjectId,\r\n organizationId: mongoose.Types.ObjectId,\r\n period: { month: number; year: number; startDate: Date; endDate: Date },\r\n dailyRate: number,\r\n expectedWorkingDays: number,\r\n session?: ClientSession\r\n ): Promise<number> {\r\n try {\r\n if (!this.models.AttendanceModel) return 0;\r\n\r\n let query = this.models.AttendanceModel.findOne({\r\n tenantId: organizationId,\r\n targetId: employeeId,\r\n targetModel: 'Employee',\r\n year: period.year,\r\n month: period.month,\r\n });\r\n if (session) query = query.session(session);\r\n\r\n const attendance = await query;\r\n if (!attendance) return 0;\r\n\r\n const workedDays = (attendance as { totalWorkDays?: number }).totalWorkDays || 0;\r\n \r\n // Calculate absent days based on expected working days (not calendar days)\r\n const absentDays = Math.max(0, expectedWorkingDays - workedDays);\r\n\r\n return Math.round(absentDays * dailyRate);\r\n } catch (error) {\r\n getLogger().warn('Failed to calculate attendance deduction', {\r\n employeeId: employeeId.toString(),\r\n error: (error as Error).message,\r\n });\r\n return 0;\r\n }\r\n }\r\n\r\n private async updatePayrollStats(\r\n employee: EmployeeDocument,\r\n amount: number,\r\n paymentDate: Date,\r\n session?: ClientSession\r\n ): Promise<void> {\r\n if (!employee.payrollStats) {\r\n employee.payrollStats = {\r\n totalPaid: 0,\r\n paymentsThisYear: 0,\r\n averageMonthly: 0,\r\n };\r\n }\r\n\r\n employee.payrollStats.totalPaid = (employee.payrollStats.totalPaid || 0) + amount;\r\n employee.payrollStats.lastPaymentDate = paymentDate;\r\n employee.payrollStats.paymentsThisYear = (employee.payrollStats.paymentsThisYear || 0) + 1;\r\n employee.payrollStats.averageMonthly = Math.round(\r\n employee.payrollStats.totalPaid / employee.payrollStats.paymentsThisYear\r\n );\r\n employee.payrollStats.nextPaymentDate = addMonths(paymentDate, 1);\r\n\r\n await employee.save(session ? { session } : {});\r\n }\r\n\r\n // ========================================\r\n // Static Factory\r\n // ========================================\r\n\r\n /**\r\n * Create a new Payroll instance\r\n */\r\n static create(): Payroll {\r\n return new Payroll();\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Payroll Builder\r\n// ============================================================================\r\n\r\nexport interface ModelsConfig {\r\n EmployeeModel: Model<any>;\r\n PayrollRecordModel: Model<any>;\r\n TransactionModel: Model<any>;\r\n AttendanceModel?: Model<any> | null;\r\n}\r\n\r\nexport interface PayrollBuilderOptions {\r\n models?: ModelsConfig;\r\n config?: DeepPartial<HRMConfig>;\r\n singleTenant?: SingleTenantConfig | null;\r\n logger?: Logger;\r\n}\r\n\r\nexport class PayrollBuilder {\r\n private _models: ModelsConfig | null = null;\r\n private _config: DeepPartial<HRMConfig> | undefined;\r\n private _singleTenant: SingleTenantConfig | null = null;\r\n private _logger: Logger | undefined;\r\n\r\n /**\r\n * Set models\r\n */\r\n withModels(models: ModelsConfig): this {\r\n this._models = models;\r\n return this;\r\n }\r\n\r\n /**\r\n * Set config overrides\r\n */\r\n withConfig(config: DeepPartial<HRMConfig>): this {\r\n this._config = config;\r\n return this;\r\n }\r\n\r\n /**\r\n * Enable single-tenant mode\r\n * \r\n * Use this when building a single-organization HRM (no organizationId needed)\r\n * \r\n * @example\r\n * ```typescript\r\n * const payroll = createPayrollInstance()\r\n * .withModels({ EmployeeModel, PayrollRecordModel, TransactionModel })\r\n * .withSingleTenant({ organizationId: 'my-company' })\r\n * .build();\r\n * ```\r\n */\r\n withSingleTenant(config: SingleTenantConfig): this {\r\n this._singleTenant = config;\r\n return this;\r\n }\r\n\r\n /**\r\n * Enable single-tenant mode (shorthand)\r\n * \r\n * Alias for withSingleTenant() - consistent with @classytic/clockin API\r\n * \r\n * @example\r\n * ```typescript\r\n * const payroll = createPayrollInstance()\r\n * .withModels({ ... })\r\n * .forSingleTenant() // ← No organizationId needed!\r\n * .build();\r\n * ```\r\n */\r\n forSingleTenant(config: SingleTenantConfig = {}): this {\r\n return this.withSingleTenant(config);\r\n }\r\n\r\n /**\r\n * Set custom logger\r\n */\r\n withLogger(logger: Logger): this {\r\n this._logger = logger;\r\n return this;\r\n }\r\n\r\n /**\r\n * Build and initialize Payroll instance\r\n */\r\n build(): Payroll {\r\n if (!this._models) {\r\n throw new Error('Models are required. Call withModels() first.');\r\n }\r\n\r\n const payroll = new Payroll();\r\n payroll.initialize({\r\n EmployeeModel: this._models.EmployeeModel,\r\n PayrollRecordModel: this._models.PayrollRecordModel,\r\n TransactionModel: this._models.TransactionModel,\r\n AttendanceModel: this._models.AttendanceModel,\r\n config: this._config,\r\n singleTenant: this._singleTenant,\r\n logger: this._logger,\r\n });\r\n\r\n return payroll;\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Factory Function\r\n// ============================================================================\r\n\r\n/**\r\n * Create a new Payroll builder\r\n */\r\nexport function createPayrollInstance(): PayrollBuilder {\r\n return new PayrollBuilder();\r\n}\r\n\r\n// ============================================================================\r\n// Singleton Instance\r\n// ============================================================================\r\n\r\nlet payrollInstance: Payroll | null = null;\r\n\r\n/**\r\n * Get or create singleton Payroll instance\r\n */\r\nexport function getPayroll(): Payroll {\r\n if (!payrollInstance) {\r\n payrollInstance = new Payroll();\r\n }\r\n return payrollInstance;\r\n}\r\n\r\n/**\r\n * Reset singleton (for testing)\r\n */\r\nexport function resetPayroll(): void {\r\n payrollInstance = null;\r\n Container.resetInstance();\r\n}\r\n\r\n// ============================================================================\r\n// Exports\r\n// ============================================================================\r\n\r\nexport const payroll = getPayroll();\r\nexport default payroll;\r\n","/**\r\n * @classytic/payroll - Mongoose Schemas\r\n *\r\n * Reusable schema definitions for employee and payroll models\r\n * Can be spread into your own schemas\r\n */\r\n\r\nimport mongoose, { Schema, type SchemaDefinition } from 'mongoose';\r\nimport {\r\n EMPLOYMENT_TYPE_VALUES,\r\n EMPLOYEE_STATUS_VALUES,\r\n DEPARTMENT_VALUES,\r\n PAYMENT_FREQUENCY_VALUES,\r\n ALLOWANCE_TYPE_VALUES,\r\n DEDUCTION_TYPE_VALUES,\r\n TERMINATION_REASON_VALUES,\r\n PAYROLL_STATUS_VALUES,\r\n} from '../enums.js';\r\nimport { HRM_CONFIG } from '../config.js';\r\n\r\n// ============================================================================\r\n// Sub-Schemas\r\n// ============================================================================\r\n\r\n/**\r\n * Allowance schema definition\r\n */\r\nexport const allowanceSchema = new Schema(\r\n {\r\n type: {\r\n type: String,\r\n enum: ALLOWANCE_TYPE_VALUES,\r\n required: true,\r\n },\r\n name: { type: String },\r\n amount: { type: Number, required: true, min: 0 },\r\n isPercentage: { type: Boolean, default: false },\r\n value: { type: Number },\r\n taxable: { type: Boolean, default: true },\r\n recurring: { type: Boolean, default: true },\r\n effectiveFrom: { type: Date, default: () => new Date() },\r\n effectiveTo: { type: Date },\r\n },\r\n { _id: false }\r\n);\r\n\r\n/**\r\n * Deduction schema definition\r\n */\r\nexport const deductionSchema = new Schema(\r\n {\r\n type: {\r\n type: String,\r\n enum: DEDUCTION_TYPE_VALUES,\r\n required: true,\r\n },\r\n name: { type: String },\r\n amount: { type: Number, required: true, min: 0 },\r\n isPercentage: { type: Boolean, default: false },\r\n value: { type: Number },\r\n auto: { type: Boolean, default: false },\r\n recurring: { type: Boolean, default: true },\r\n effectiveFrom: { type: Date, default: () => new Date() },\r\n effectiveTo: { type: Date },\r\n description: { type: String },\r\n },\r\n { _id: false }\r\n);\r\n\r\n/**\r\n * Compensation schema definition\r\n */\r\nexport const compensationSchema = new Schema(\r\n {\r\n baseAmount: { type: Number, required: true, min: 0 },\r\n frequency: {\r\n type: String,\r\n enum: PAYMENT_FREQUENCY_VALUES,\r\n default: 'monthly',\r\n },\r\n currency: { type: String, default: 'BDT' },\r\n allowances: [allowanceSchema],\r\n deductions: [deductionSchema],\r\n grossSalary: { type: Number, default: 0 },\r\n netSalary: { type: Number, default: 0 },\r\n effectiveFrom: { type: Date, default: () => new Date() },\r\n lastModified: { type: Date, default: () => new Date() },\r\n },\r\n { _id: false }\r\n);\r\n\r\n/**\r\n * Work schedule schema definition\r\n */\r\nexport const workScheduleSchema = new Schema(\r\n {\r\n hoursPerWeek: { type: Number, min: 0, max: 168 },\r\n hoursPerDay: { type: Number, min: 0, max: 24 },\r\n workingDays: [{ type: Number, min: 0, max: 6 }],\r\n shiftStart: { type: String },\r\n shiftEnd: { type: String },\r\n },\r\n { _id: false }\r\n);\r\n\r\n/**\r\n * Bank details schema definition\r\n */\r\nexport const bankDetailsSchema = new Schema(\r\n {\r\n accountName: { type: String },\r\n accountNumber: { type: String },\r\n bankName: { type: String },\r\n branchName: { type: String },\r\n routingNumber: { type: String },\r\n },\r\n { _id: false }\r\n);\r\n\r\n/**\r\n * Employment history entry schema\r\n */\r\nexport const employmentHistorySchema = new Schema(\r\n {\r\n hireDate: { type: Date, required: true },\r\n terminationDate: { type: Date, required: true },\r\n reason: { type: String, enum: TERMINATION_REASON_VALUES },\r\n finalSalary: { type: Number },\r\n position: { type: String },\r\n department: { type: String },\r\n notes: { type: String },\r\n },\r\n { timestamps: true }\r\n);\r\n\r\n/**\r\n * Payroll stats schema (pre-calculated)\r\n */\r\nexport const payrollStatsSchema = new Schema(\r\n {\r\n totalPaid: { type: Number, default: 0, min: 0 },\r\n lastPaymentDate: { type: Date },\r\n nextPaymentDate: { type: Date },\r\n paymentsThisYear: { type: Number, default: 0, min: 0 },\r\n averageMonthly: { type: Number, default: 0, min: 0 },\r\n updatedAt: { type: Date, default: () => new Date() },\r\n },\r\n { _id: false }\r\n);\r\n\r\n// ============================================================================\r\n// Employment Fields (Spread into Employee Schema)\r\n// ============================================================================\r\n\r\n/**\r\n * Employment fields to spread into your Employee schema\r\n * \r\n * @example\r\n * const employeeSchema = new Schema({\r\n * ...employmentFields,\r\n * // Your custom fields\r\n * certifications: [{ name: String, issuedDate: Date }],\r\n * });\r\n */\r\nexport const employmentFields: SchemaDefinition = {\r\n userId: {\r\n type: Schema.Types.ObjectId,\r\n ref: 'User',\r\n required: true,\r\n },\r\n organizationId: {\r\n type: Schema.Types.ObjectId,\r\n ref: 'Organization',\r\n required: true,\r\n },\r\n employeeId: { type: String, required: true },\r\n employmentType: {\r\n type: String,\r\n enum: EMPLOYMENT_TYPE_VALUES,\r\n default: 'full_time',\r\n },\r\n status: {\r\n type: String,\r\n enum: EMPLOYEE_STATUS_VALUES,\r\n default: 'active',\r\n },\r\n department: { type: String, enum: DEPARTMENT_VALUES },\r\n position: { type: String, required: true },\r\n hireDate: { type: Date, required: true },\r\n terminationDate: { type: Date },\r\n probationEndDate: { type: Date },\r\n employmentHistory: [employmentHistorySchema],\r\n compensation: { type: compensationSchema, required: true },\r\n workSchedule: workScheduleSchema,\r\n bankDetails: bankDetailsSchema,\r\n payrollStats: { type: payrollStatsSchema, default: () => ({}) },\r\n};\r\n\r\n// ============================================================================\r\n// Payroll Record Sub-Schemas\r\n// ============================================================================\r\n\r\n/**\r\n * Payroll breakdown schema\r\n */\r\nexport const payrollBreakdownSchema = new Schema(\r\n {\r\n baseAmount: { type: Number, required: true, min: 0 },\r\n allowances: [\r\n {\r\n type: { type: String },\r\n amount: { type: Number, min: 0 },\r\n taxable: { type: Boolean, default: true },\r\n },\r\n ],\r\n deductions: [\r\n {\r\n type: { type: String },\r\n amount: { type: Number, min: 0 },\r\n description: { type: String },\r\n },\r\n ],\r\n grossSalary: { type: Number, required: true, min: 0 },\r\n netSalary: { type: Number, required: true, min: 0 },\r\n workingDays: { type: Number, min: 0 },\r\n actualDays: { type: Number, min: 0 },\r\n proRatedAmount: { type: Number, default: 0, min: 0 },\r\n attendanceDeduction: { type: Number, default: 0, min: 0 },\r\n overtimeAmount: { type: Number, default: 0, min: 0 },\r\n bonusAmount: { type: Number, default: 0, min: 0 },\r\n },\r\n { _id: false }\r\n);\r\n\r\n/**\r\n * Payroll period schema\r\n */\r\nexport const periodSchema = new Schema(\r\n {\r\n month: { type: Number, required: true, min: 1, max: 12 },\r\n year: { type: Number, required: true, min: 2020 },\r\n startDate: { type: Date, required: true },\r\n endDate: { type: Date, required: true },\r\n payDate: { type: Date, required: true },\r\n },\r\n { _id: false }\r\n);\r\n\r\n/**\r\n * Payroll record fields to spread into PayrollRecord schema\r\n */\r\nexport const payrollRecordFields: SchemaDefinition = {\r\n organizationId: {\r\n type: Schema.Types.ObjectId,\r\n ref: 'Organization',\r\n required: true,\r\n index: true,\r\n },\r\n employeeId: {\r\n type: Schema.Types.ObjectId,\r\n required: true,\r\n index: true,\r\n },\r\n userId: {\r\n type: Schema.Types.ObjectId,\r\n ref: 'User',\r\n index: true,\r\n },\r\n period: { type: periodSchema, required: true },\r\n breakdown: { type: payrollBreakdownSchema, required: true },\r\n transactionId: { type: Schema.Types.ObjectId, ref: 'Transaction' },\r\n status: {\r\n type: String,\r\n enum: PAYROLL_STATUS_VALUES,\r\n default: 'pending',\r\n index: true,\r\n },\r\n paidAt: { type: Date },\r\n paymentMethod: { type: String },\r\n processedBy: { type: Schema.Types.ObjectId, ref: 'User' },\r\n notes: { type: String },\r\n payslipUrl: { type: String },\r\n exported: { type: Boolean, default: false },\r\n exportedAt: { type: Date },\r\n};\r\n\r\n// ============================================================================\r\n// Index Definitions\r\n// ============================================================================\r\n\r\n/**\r\n * Recommended indexes for Employee schema\r\n */\r\nexport const employeeIndexes = [\r\n { fields: { organizationId: 1, employeeId: 1 }, options: { unique: true } },\r\n { fields: { userId: 1, organizationId: 1 }, options: { unique: true } },\r\n { fields: { organizationId: 1, status: 1 } },\r\n { fields: { organizationId: 1, department: 1 } },\r\n { fields: { organizationId: 1, 'compensation.netSalary': -1 } },\r\n];\r\n\r\n/**\r\n * Recommended indexes for PayrollRecord schema\r\n */\r\nexport const payrollRecordIndexes = [\r\n {\r\n fields: { organizationId: 1, employeeId: 1, 'period.month': 1, 'period.year': 1 },\r\n options: { unique: true },\r\n },\r\n { fields: { organizationId: 1, 'period.year': 1, 'period.month': 1 } },\r\n { fields: { employeeId: 1, 'period.year': -1, 'period.month': -1 } },\r\n { fields: { status: 1, createdAt: -1 } },\r\n { fields: { organizationId: 1, status: 1, 'period.payDate': 1 } },\r\n {\r\n fields: { createdAt: 1 },\r\n options: {\r\n expireAfterSeconds: HRM_CONFIG.dataRetention.payrollRecordsTTL,\r\n partialFilterExpression: { exported: true },\r\n },\r\n },\r\n];\r\n\r\n/**\r\n * Apply indexes to schema\r\n */\r\nexport function applyEmployeeIndexes(schema: Schema): void {\r\n for (const { fields, options } of employeeIndexes) {\r\n schema.index(fields as unknown as Record<string, 1 | -1>, options);\r\n }\r\n}\r\n\r\n/**\r\n * Apply payroll record indexes to schema\r\n */\r\nexport function applyPayrollRecordIndexes(schema: Schema): void {\r\n for (const { fields, options } of payrollRecordIndexes) {\r\n schema.index(fields as unknown as Record<string, 1 | -1>, options);\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Complete Schema Creators\r\n// ============================================================================\r\n\r\n/**\r\n * Create a complete Employee schema with all HRM fields\r\n */\r\nexport function createEmployeeSchema(\r\n additionalFields: SchemaDefinition = {}\r\n): Schema {\r\n const schema = new Schema(\r\n {\r\n ...employmentFields,\r\n ...additionalFields,\r\n },\r\n { timestamps: true }\r\n );\r\n\r\n applyEmployeeIndexes(schema);\r\n return schema;\r\n}\r\n\r\n/**\r\n * Create a complete PayrollRecord schema\r\n */\r\nexport function createPayrollRecordSchema(\r\n additionalFields: SchemaDefinition = {}\r\n): Schema {\r\n const schema = new Schema(\r\n {\r\n ...payrollRecordFields,\r\n ...additionalFields,\r\n },\r\n { timestamps: true }\r\n );\r\n\r\n applyPayrollRecordIndexes(schema);\r\n\r\n // Virtual: totalAmount\r\n schema.virtual('totalAmount').get(function () {\r\n return this.breakdown?.netSalary || 0;\r\n });\r\n\r\n // Virtual: isPaid\r\n schema.virtual('isPaid').get(function () {\r\n return this.status === 'paid';\r\n });\r\n\r\n // Virtual: periodLabel\r\n schema.virtual('periodLabel').get(function () {\r\n const months = [\r\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\r\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',\r\n ];\r\n return `${months[this.period.month - 1]} ${this.period.year}`;\r\n });\r\n\r\n // Method: markAsPaid\r\n schema.methods.markAsPaid = function (\r\n transactionId: mongoose.Types.ObjectId,\r\n paidAt = new Date()\r\n ) {\r\n this.status = 'paid';\r\n this.transactionId = transactionId;\r\n this.paidAt = paidAt;\r\n };\r\n\r\n // Method: markAsExported\r\n schema.methods.markAsExported = function () {\r\n this.exported = true;\r\n this.exportedAt = new Date();\r\n };\r\n\r\n // Method: canBeDeleted\r\n schema.methods.canBeDeleted = function (): boolean {\r\n return this.exported && this.status === 'paid';\r\n };\r\n\r\n return schema;\r\n}\r\n\r\n\r\n// ============================================================================\r\n// Default Export\r\n// ============================================================================\r\n\r\nexport default {\r\n // Sub-schemas\r\n allowanceSchema,\r\n deductionSchema,\r\n compensationSchema,\r\n workScheduleSchema,\r\n bankDetailsSchema,\r\n employmentHistorySchema,\r\n payrollStatsSchema,\r\n payrollBreakdownSchema,\r\n periodSchema,\r\n // Fields\r\n employmentFields,\r\n payrollRecordFields,\r\n // Indexes\r\n employeeIndexes,\r\n payrollRecordIndexes,\r\n applyEmployeeIndexes,\r\n applyPayrollRecordIndexes,\r\n // Schema creators\r\n createEmployeeSchema,\r\n createPayrollRecordSchema,\r\n};\r\n\r\n","/**\r\n * @classytic/payroll - PayrollRecord Model\r\n *\r\n * Mongoose schema for payroll records with TTL and auto-export\r\n */\r\n\r\nimport mongoose, { Schema, Model } from 'mongoose';\r\nimport type { PayrollRecordDocument, PayrollStatus, PaymentMethod, PayrollBreakdown } from '../types.js';\r\nimport { HRM_CONFIG } from '../config.js';\r\nimport { PAYROLL_STATUS } from '../enums.js';\r\nimport { logger } from '../utils/logger.js';\r\n\r\n// ============================================================================\r\n// Schema Definition\r\n// ============================================================================\r\n\r\nconst allowanceBreakdownSchema = new Schema(\r\n {\r\n type: { type: String, required: true },\r\n amount: { type: Number, required: true },\r\n taxable: { type: Boolean, default: true },\r\n },\r\n { _id: false }\r\n);\r\n\r\nconst deductionBreakdownSchema = new Schema(\r\n {\r\n type: { type: String, required: true },\r\n amount: { type: Number, required: true },\r\n description: { type: String },\r\n },\r\n { _id: false }\r\n);\r\n\r\nconst breakdownSchema = new Schema(\r\n {\r\n baseAmount: { type: Number, required: true },\r\n allowances: [allowanceBreakdownSchema],\r\n deductions: [deductionBreakdownSchema],\r\n grossSalary: { type: Number, required: true },\r\n netSalary: { type: Number, required: true },\r\n taxableAmount: { type: Number, default: 0 },\r\n taxAmount: { type: Number, default: 0 },\r\n workingDays: { type: Number },\r\n actualDays: { type: Number },\r\n proRatedAmount: { type: Number, default: 0 },\r\n attendanceDeduction: { type: Number, default: 0 },\r\n },\r\n { _id: false }\r\n);\r\n\r\nconst periodSchema = new Schema(\r\n {\r\n month: { type: Number, required: true, min: 1, max: 12 },\r\n year: { type: Number, required: true },\r\n startDate: { type: Date, required: true },\r\n endDate: { type: Date, required: true },\r\n payDate: { type: Date },\r\n },\r\n { _id: false }\r\n);\r\n\r\nconst payrollRecordSchema = new Schema(\r\n {\r\n organizationId: {\r\n type: Schema.Types.ObjectId,\r\n required: true,\r\n ref: 'Organization',\r\n index: true,\r\n },\r\n employeeId: {\r\n type: Schema.Types.ObjectId,\r\n required: true,\r\n ref: 'Employee',\r\n index: true,\r\n },\r\n userId: {\r\n type: Schema.Types.ObjectId,\r\n required: true,\r\n ref: 'User',\r\n index: true,\r\n },\r\n period: {\r\n type: periodSchema,\r\n required: true,\r\n },\r\n breakdown: {\r\n type: breakdownSchema,\r\n required: true,\r\n },\r\n status: {\r\n type: String,\r\n enum: Object.values(PAYROLL_STATUS),\r\n default: PAYROLL_STATUS.PENDING,\r\n index: true,\r\n },\r\n paymentMethod: {\r\n type: String,\r\n enum: ['cash', 'bank', 'check', 'mobile', 'bkash', 'nagad', 'rocket'],\r\n default: 'bank',\r\n },\r\n transactionId: {\r\n type: Schema.Types.ObjectId,\r\n ref: 'Transaction',\r\n },\r\n paidAt: Date,\r\n processedAt: Date,\r\n processedBy: {\r\n type: Schema.Types.ObjectId,\r\n ref: 'User',\r\n },\r\n notes: String,\r\n metadata: {\r\n type: Schema.Types.Mixed,\r\n default: {},\r\n },\r\n exported: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n exportedAt: Date,\r\n corrections: [\r\n {\r\n previousAmount: Number,\r\n newAmount: Number,\r\n reason: String,\r\n correctedBy: { type: Schema.Types.ObjectId, ref: 'User' },\r\n correctedAt: { type: Date, default: Date.now },\r\n },\r\n ],\r\n },\r\n {\r\n timestamps: true,\r\n }\r\n);\r\n\r\n// ============================================================================\r\n// Indexes\r\n// ============================================================================\r\n\r\npayrollRecordSchema.index({ organizationId: 1, 'period.month': 1, 'period.year': 1 });\r\npayrollRecordSchema.index({ employeeId: 1, 'period.month': 1, 'period.year': 1 }, { unique: true });\r\npayrollRecordSchema.index({ organizationId: 1, status: 1 });\r\npayrollRecordSchema.index({ createdAt: 1 }, { expireAfterSeconds: HRM_CONFIG.dataRetention.payrollRecordsTTL });\r\n\r\n// ============================================================================\r\n// Virtuals\r\n// ============================================================================\r\n\r\npayrollRecordSchema.virtual('isPaid').get(function () {\r\n return this.status === PAYROLL_STATUS.PAID;\r\n});\r\n\r\npayrollRecordSchema.virtual('totalDeductions').get(function () {\r\n return (this.breakdown?.deductions || []).reduce(\r\n (sum: number, d: { amount: number }) => sum + d.amount,\r\n 0\r\n );\r\n});\r\n\r\npayrollRecordSchema.virtual('totalAllowances').get(function () {\r\n return (this.breakdown?.allowances || []).reduce(\r\n (sum: number, a: { amount: number }) => sum + a.amount,\r\n 0\r\n );\r\n});\r\n\r\n// ============================================================================\r\n// Methods\r\n// ============================================================================\r\n\r\npayrollRecordSchema.methods.markAsPaid = function (\r\n transactionId: mongoose.Types.ObjectId,\r\n paidAt = new Date()\r\n) {\r\n this.status = PAYROLL_STATUS.PAID;\r\n this.transactionId = transactionId;\r\n this.paidAt = paidAt;\r\n};\r\n\r\npayrollRecordSchema.methods.markAsCancelled = function (reason: string) {\r\n if (this.status === PAYROLL_STATUS.PAID) {\r\n throw new Error('Cannot cancel paid payroll record');\r\n }\r\n this.status = PAYROLL_STATUS.CANCELLED;\r\n this.notes = (this.notes || '') + `\\nCancelled: ${reason}`;\r\n};\r\n\r\npayrollRecordSchema.methods.addCorrection = function (\r\n previousAmount: number,\r\n newAmount: number,\r\n reason: string,\r\n correctedBy: mongoose.Types.ObjectId\r\n) {\r\n if (!this.corrections) {\r\n this.corrections = [];\r\n }\r\n this.corrections.push({\r\n previousAmount,\r\n newAmount,\r\n reason,\r\n correctedBy,\r\n correctedAt: new Date(),\r\n });\r\n\r\n this.breakdown.netSalary = newAmount;\r\n logger.info('Payroll correction added', {\r\n recordId: this._id.toString(),\r\n previousAmount,\r\n newAmount,\r\n reason,\r\n });\r\n};\r\n\r\npayrollRecordSchema.methods.getBreakdownSummary = function () {\r\n const { baseAmount, allowances, deductions, grossSalary, netSalary } = this.breakdown;\r\n return {\r\n base: baseAmount,\r\n totalAllowances: (allowances || []).reduce(\r\n (sum: number, a: { amount: number }) => sum + a.amount,\r\n 0\r\n ),\r\n totalDeductions: (deductions || []).reduce(\r\n (sum: number, d: { amount: number }) => sum + d.amount,\r\n 0\r\n ),\r\n gross: grossSalary,\r\n net: netSalary,\r\n };\r\n};\r\n\r\n// ============================================================================\r\n// Statics\r\n// ============================================================================\r\n\r\npayrollRecordSchema.statics.findByPeriod = function (\r\n organizationId: mongoose.Types.ObjectId,\r\n month: number,\r\n year: number\r\n) {\r\n return this.find({\r\n organizationId,\r\n 'period.month': month,\r\n 'period.year': year,\r\n });\r\n};\r\n\r\npayrollRecordSchema.statics.findByEmployee = function (\r\n employeeId: mongoose.Types.ObjectId,\r\n limit = 12\r\n) {\r\n return this.find({ employeeId })\r\n .sort({ 'period.year': -1, 'period.month': -1 })\r\n .limit(limit);\r\n};\r\n\r\npayrollRecordSchema.statics.getSummary = function (\r\n organizationId: mongoose.Types.ObjectId,\r\n month?: number,\r\n year?: number\r\n) {\r\n const match: Record<string, unknown> = { organizationId };\r\n if (month) match['period.month'] = month;\r\n if (year) match['period.year'] = year;\r\n\r\n return this.aggregate([\r\n { $match: match },\r\n {\r\n $group: {\r\n _id: null,\r\n totalGross: { $sum: '$breakdown.grossSalary' },\r\n totalNet: { $sum: '$breakdown.netSalary' },\r\n count: { $sum: 1 },\r\n paidCount: {\r\n $sum: { $cond: [{ $eq: ['$status', PAYROLL_STATUS.PAID] }, 1, 0] },\r\n },\r\n },\r\n },\r\n ]).then((results: unknown[]) => results[0] || { totalGross: 0, totalNet: 0, count: 0, paidCount: 0 });\r\n};\r\n\r\npayrollRecordSchema.statics.getExpiringSoon = function (\r\n organizationId: mongoose.Types.ObjectId,\r\n daysBeforeExpiry = 30\r\n) {\r\n const expiryThreshold = new Date();\r\n expiryThreshold.setSeconds(\r\n expiryThreshold.getSeconds() + HRM_CONFIG.dataRetention.payrollRecordsTTL - daysBeforeExpiry * 24 * 60 * 60\r\n );\r\n\r\n return this.find({\r\n organizationId,\r\n exported: false,\r\n createdAt: { $lte: expiryThreshold },\r\n });\r\n};\r\n\r\n// ============================================================================\r\n// Model Creation\r\n// ============================================================================\r\n\r\nexport interface PayrollRecordModel extends Model<PayrollRecordDocument> {\r\n findByPeriod(\r\n organizationId: mongoose.Types.ObjectId,\r\n month: number,\r\n year: number\r\n ): ReturnType<Model<PayrollRecordDocument>['find']>;\r\n findByEmployee(\r\n employeeId: mongoose.Types.ObjectId,\r\n limit?: number\r\n ): ReturnType<Model<PayrollRecordDocument>['find']>;\r\n getSummary(\r\n organizationId: mongoose.Types.ObjectId,\r\n month?: number,\r\n year?: number\r\n ): Promise<{\r\n totalGross: number;\r\n totalNet: number;\r\n count: number;\r\n paidCount: number;\r\n }>;\r\n getExpiringSoon(\r\n organizationId: mongoose.Types.ObjectId,\r\n daysBeforeExpiry?: number\r\n ): ReturnType<Model<PayrollRecordDocument>['find']>;\r\n}\r\n\r\n/**\r\n * Get or create PayrollRecord model\r\n */\r\nexport function getPayrollRecordModel(\r\n connection: mongoose.Connection = mongoose.connection\r\n): PayrollRecordModel {\r\n const modelName = 'PayrollRecord';\r\n \r\n if (connection.models[modelName]) {\r\n return connection.models[modelName] as PayrollRecordModel;\r\n }\r\n\r\n return connection.model<PayrollRecordDocument, PayrollRecordModel>(\r\n modelName,\r\n payrollRecordSchema\r\n );\r\n}\r\n\r\nexport { payrollRecordSchema };\r\nexport default payrollRecordSchema;\r\n\r\n","/**\r\n * @classytic/payroll - Validation Utilities\r\n *\r\n * Fluent, composable, type-safe validation\r\n * Clear semantics and helpful error messages\r\n */\r\n\r\nimport type {\r\n EmployeeStatus,\r\n EmploymentType,\r\n Compensation,\r\n BankDetails,\r\n EmployeeValidationResult,\r\n} from '../types.js';\r\nimport {\r\n EMPLOYEE_STATUS_VALUES,\r\n EMPLOYMENT_TYPE_VALUES,\r\n} from '../enums.js';\r\nimport { diffInMonths } from './date.js';\r\n\r\n// ============================================================================\r\n// Employee Status Validators\r\n// ============================================================================\r\n\r\n/**\r\n * Check if employee is active\r\n */\r\nexport function isActive(employee: { status?: EmployeeStatus }): boolean {\r\n return employee?.status === 'active';\r\n}\r\n\r\n/**\r\n * Check if employee is on leave\r\n */\r\nexport function isOnLeave(employee: { status?: EmployeeStatus }): boolean {\r\n return employee?.status === 'on_leave';\r\n}\r\n\r\n/**\r\n * Check if employee is suspended\r\n */\r\nexport function isSuspended(employee: { status?: EmployeeStatus }): boolean {\r\n return employee?.status === 'suspended';\r\n}\r\n\r\n/**\r\n * Check if employee is terminated\r\n */\r\nexport function isTerminated(employee: { status?: EmployeeStatus }): boolean {\r\n return employee?.status === 'terminated';\r\n}\r\n\r\n/**\r\n * Check if employee is employed (not terminated)\r\n */\r\nexport function isEmployed(employee: { status?: EmployeeStatus }): boolean {\r\n return (\r\n isActive(employee) || isOnLeave(employee) || isSuspended(employee)\r\n );\r\n}\r\n\r\n/**\r\n * Check if employee can receive salary\r\n */\r\nexport function canReceiveSalary(employee: {\r\n status?: EmployeeStatus;\r\n compensation?: { baseAmount?: number };\r\n}): boolean {\r\n return (\r\n (isActive(employee) || isOnLeave(employee)) &&\r\n (employee.compensation?.baseAmount ?? 0) > 0\r\n );\r\n}\r\n\r\n/**\r\n * Check if employment can be updated\r\n */\r\nexport function canUpdateEmployment(employee: { status?: EmployeeStatus }): boolean {\r\n return !isTerminated(employee);\r\n}\r\n\r\n// ============================================================================\r\n// Compensation Validators\r\n// ============================================================================\r\n\r\n/**\r\n * Check if employee has valid compensation\r\n */\r\nexport function hasCompensation(employee: {\r\n compensation?: { baseAmount?: number };\r\n}): boolean {\r\n return (employee.compensation?.baseAmount ?? 0) > 0;\r\n}\r\n\r\n/**\r\n * Check if compensation is valid\r\n */\r\nexport function isValidCompensation(compensation?: Compensation): boolean {\r\n return !!(\r\n compensation?.baseAmount &&\r\n compensation.baseAmount > 0 &&\r\n compensation.frequency &&\r\n compensation.currency\r\n );\r\n}\r\n\r\n/**\r\n * Check if bank details are valid\r\n */\r\nexport function isValidBankDetails(bankDetails?: BankDetails): boolean {\r\n return !!(\r\n bankDetails?.accountNumber &&\r\n bankDetails.bankName &&\r\n bankDetails.accountName\r\n );\r\n}\r\n\r\n// ============================================================================\r\n// Probation Validators\r\n// ============================================================================\r\n\r\n/**\r\n * Check if employee is in probation\r\n */\r\nexport function isInProbation(\r\n employee: { probationEndDate?: Date | null },\r\n now = new Date()\r\n): boolean {\r\n if (!employee?.probationEndDate) return false;\r\n return new Date(employee.probationEndDate) > now;\r\n}\r\n\r\n/**\r\n * Check if employee has completed probation\r\n */\r\nexport function hasCompletedProbation(\r\n employee: { probationEndDate?: Date | null },\r\n now = new Date()\r\n): boolean {\r\n if (!employee?.probationEndDate) return true;\r\n return new Date(employee.probationEndDate) <= now;\r\n}\r\n\r\n// ============================================================================\r\n// Eligibility Validators\r\n// ============================================================================\r\n\r\n/**\r\n * Check if employee is eligible for bonus\r\n */\r\nexport function isEligibleForBonus(\r\n employee: { status?: EmployeeStatus; hireDate?: Date },\r\n requiredMonths = 6\r\n): boolean {\r\n if (!isActive(employee) || !employee.hireDate) return false;\r\n const monthsEmployed = diffInMonths(employee.hireDate, new Date());\r\n return monthsEmployed >= requiredMonths;\r\n}\r\n\r\n/**\r\n * Check if employee is eligible for payroll\r\n */\r\nexport function isEligibleForPayroll(employee: {\r\n status?: EmployeeStatus;\r\n compensation?: { baseAmount?: number };\r\n bankDetails?: BankDetails;\r\n}): { eligible: boolean; reasons: string[] } {\r\n const reasons: string[] = [];\r\n\r\n if (!isActive(employee) && !isOnLeave(employee)) {\r\n reasons.push('Employee is not in active or on-leave status');\r\n }\r\n\r\n if (!hasCompensation(employee)) {\r\n reasons.push('Employee has no valid compensation');\r\n }\r\n\r\n return {\r\n eligible: reasons.length === 0,\r\n reasons,\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Field Validators\r\n// ============================================================================\r\n\r\n/**\r\n * Check if value is required\r\n */\r\nexport function required(fieldName: string): (value: unknown) => string | true {\r\n return (value: unknown) =>\r\n value !== undefined && value !== null && value !== ''\r\n ? true\r\n : `${fieldName} is required`;\r\n}\r\n\r\n/**\r\n * Check minimum value\r\n */\r\nexport function min(\r\n minValue: number,\r\n fieldName: string\r\n): (value: number) => string | true {\r\n return (value: number) =>\r\n value >= minValue ? true : `${fieldName} must be at least ${minValue}`;\r\n}\r\n\r\n/**\r\n * Check maximum value\r\n */\r\nexport function max(\r\n maxValue: number,\r\n fieldName: string\r\n): (value: number) => string | true {\r\n return (value: number) =>\r\n value <= maxValue ? true : `${fieldName} must not exceed ${maxValue}`;\r\n}\r\n\r\n/**\r\n * Check value is in range\r\n */\r\nexport function inRange(\r\n minValue: number,\r\n maxValue: number,\r\n fieldName: string\r\n): (value: number) => string | true {\r\n return (value: number) =>\r\n value >= minValue && value <= maxValue\r\n ? true\r\n : `${fieldName} must be between ${minValue} and ${maxValue}`;\r\n}\r\n\r\n/**\r\n * Check value is positive\r\n */\r\nexport function isPositive(fieldName: string): (value: number) => string | true {\r\n return (value: number) =>\r\n value > 0 ? true : `${fieldName} must be positive`;\r\n}\r\n\r\n/**\r\n * Check value is one of allowed values\r\n */\r\nexport function oneOf<T extends string>(\r\n allowedValues: readonly T[],\r\n fieldName: string\r\n): (value: T) => string | true {\r\n return (value: T) =>\r\n allowedValues.includes(value)\r\n ? true\r\n : `${fieldName} must be one of: ${allowedValues.join(', ')}`;\r\n}\r\n\r\n// ============================================================================\r\n// Enum Validators\r\n// ============================================================================\r\n\r\n/**\r\n * Check if status is valid\r\n */\r\nexport function isValidStatus(value: string): value is EmployeeStatus {\r\n return EMPLOYEE_STATUS_VALUES.includes(value as EmployeeStatus);\r\n}\r\n\r\n/**\r\n * Check if employment type is valid\r\n */\r\nexport function isValidEmploymentType(value: string): value is EmploymentType {\r\n return EMPLOYMENT_TYPE_VALUES.includes(value as EmploymentType);\r\n}\r\n\r\n// ============================================================================\r\n// Composite Validators\r\n// ============================================================================\r\n\r\n/**\r\n * Compose multiple validators\r\n */\r\nexport function composeValidators<T>(\r\n ...validators: Array<(value: T, data?: unknown) => string | true>\r\n): (value: T, data?: unknown) => string | true {\r\n return (value: T, data?: unknown) => {\r\n for (const validator of validators) {\r\n const result = validator(value, data);\r\n if (result !== true) return result;\r\n }\r\n return true;\r\n };\r\n}\r\n\r\n/**\r\n * Create a validator from validation functions\r\n */\r\nexport function createValidator<T extends Record<string, unknown>>(\r\n validationFns: Record<string, (value: unknown, data: T) => string | true>\r\n): (data: T) => EmployeeValidationResult {\r\n return (data: T) => {\r\n const errors: string[] = [];\r\n\r\n for (const [field, validator] of Object.entries(validationFns)) {\r\n const result = validator((data as Record<string, unknown>)[field], data);\r\n if (result !== true) {\r\n errors.push(result);\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * Validate required fields exist\r\n */\r\nexport function hasRequiredFields(\r\n obj: Record<string, unknown>,\r\n fields: string[]\r\n): { valid: boolean; missing: string[] } {\r\n const missing = fields.filter(\r\n (field) => obj[field] === undefined || obj[field] === null\r\n );\r\n return {\r\n valid: missing.length === 0,\r\n missing,\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Aliases for backwards compatibility\r\n// ============================================================================\r\n\r\nexport const minValue = min;\r\nexport const maxValue = max;\r\nexport const isInRange = inRange;\r\n\r\n// ============================================================================\r\n// Default Export\r\n// ============================================================================\r\n\r\nexport default {\r\n // Status validators\r\n isActive,\r\n isOnLeave,\r\n isSuspended,\r\n isTerminated,\r\n isEmployed,\r\n canReceiveSalary,\r\n canUpdateEmployment,\r\n // Compensation validators\r\n hasCompensation,\r\n isValidCompensation,\r\n isValidBankDetails,\r\n // Probation validators\r\n isInProbation,\r\n hasCompletedProbation,\r\n // Eligibility validators\r\n isEligibleForBonus,\r\n isEligibleForPayroll,\r\n // Field validators\r\n required,\r\n min,\r\n max,\r\n inRange,\r\n isPositive,\r\n oneOf,\r\n // Enum validators\r\n isValidStatus,\r\n isValidEmploymentType,\r\n // Composite validators\r\n composeValidators,\r\n createValidator,\r\n hasRequiredFields,\r\n};\r\n\r\n","/**\r\n * @classytic/payroll - Compensation Factory\r\n *\r\n * Clean compensation structure creation\r\n * Presets for common compensation packages\r\n */\r\n\r\nimport type {\r\n Compensation,\r\n Allowance,\r\n Deduction,\r\n PaymentFrequency,\r\n CompensationBreakdownResult,\r\n} from '../types.js';\r\nimport { calculateGross, calculateNet, applyPercentage } from '../utils/calculation.js';\r\nimport { HRM_CONFIG } from '../config.js';\r\n\r\n// ============================================================================\r\n// Compensation Factory Types\r\n// ============================================================================\r\n\r\nexport interface CreateCompensationParams {\r\n baseAmount: number;\r\n frequency?: PaymentFrequency;\r\n currency?: string;\r\n allowances?: Array<{\r\n type: Allowance['type'];\r\n value: number;\r\n isPercentage?: boolean;\r\n name?: string;\r\n taxable?: boolean;\r\n }>;\r\n deductions?: Array<{\r\n type: Deduction['type'];\r\n value: number;\r\n isPercentage?: boolean;\r\n name?: string;\r\n auto?: boolean;\r\n }>;\r\n effectiveFrom?: Date;\r\n}\r\n\r\n// ============================================================================\r\n// Compensation Factory\r\n// ============================================================================\r\n\r\nexport class CompensationFactory {\r\n /**\r\n * Create compensation object\r\n */\r\n static create(params: CreateCompensationParams): Compensation {\r\n const {\r\n baseAmount,\r\n frequency = 'monthly',\r\n currency = HRM_CONFIG.payroll.defaultCurrency,\r\n allowances = [],\r\n deductions = [],\r\n effectiveFrom = new Date(),\r\n } = params;\r\n\r\n return {\r\n baseAmount,\r\n frequency,\r\n currency,\r\n allowances: allowances.map((a) => this.createAllowance(a, baseAmount)),\r\n deductions: deductions.map((d) => this.createDeduction(d, baseAmount)),\r\n effectiveFrom,\r\n lastModified: new Date(),\r\n };\r\n }\r\n\r\n /**\r\n * Create allowance\r\n */\r\n static createAllowance(\r\n params: {\r\n type: Allowance['type'];\r\n value: number;\r\n isPercentage?: boolean;\r\n name?: string;\r\n taxable?: boolean;\r\n },\r\n baseAmount?: number\r\n ): Allowance {\r\n const amount = params.isPercentage && baseAmount\r\n ? applyPercentage(baseAmount, params.value)\r\n : params.value;\r\n\r\n return {\r\n type: params.type,\r\n name: params.name || params.type,\r\n amount,\r\n isPercentage: params.isPercentage ?? false,\r\n value: params.isPercentage ? params.value : undefined,\r\n taxable: params.taxable ?? true,\r\n recurring: true,\r\n effectiveFrom: new Date(),\r\n };\r\n }\r\n\r\n /**\r\n * Create deduction\r\n */\r\n static createDeduction(\r\n params: {\r\n type: Deduction['type'];\r\n value: number;\r\n isPercentage?: boolean;\r\n name?: string;\r\n auto?: boolean;\r\n },\r\n baseAmount?: number\r\n ): Deduction {\r\n const amount = params.isPercentage && baseAmount\r\n ? applyPercentage(baseAmount, params.value)\r\n : params.value;\r\n\r\n return {\r\n type: params.type,\r\n name: params.name || params.type,\r\n amount,\r\n isPercentage: params.isPercentage ?? false,\r\n value: params.isPercentage ? params.value : undefined,\r\n auto: params.auto ?? false,\r\n recurring: true,\r\n effectiveFrom: new Date(),\r\n };\r\n }\r\n\r\n /**\r\n * Update base amount (immutable)\r\n */\r\n static updateBaseAmount(\r\n compensation: Compensation,\r\n newAmount: number,\r\n effectiveFrom = new Date()\r\n ): Compensation {\r\n return {\r\n ...compensation,\r\n baseAmount: newAmount,\r\n lastModified: effectiveFrom,\r\n };\r\n }\r\n\r\n /**\r\n * Add allowance (immutable)\r\n */\r\n static addAllowance(\r\n compensation: Compensation,\r\n allowance: Parameters<typeof this.createAllowance>[0]\r\n ): Compensation {\r\n return {\r\n ...compensation,\r\n allowances: [\r\n ...compensation.allowances,\r\n this.createAllowance(allowance, compensation.baseAmount),\r\n ],\r\n lastModified: new Date(),\r\n };\r\n }\r\n\r\n /**\r\n * Remove allowance (immutable)\r\n */\r\n static removeAllowance(\r\n compensation: Compensation,\r\n allowanceType: Allowance['type']\r\n ): Compensation {\r\n return {\r\n ...compensation,\r\n allowances: compensation.allowances.filter((a) => a.type !== allowanceType),\r\n lastModified: new Date(),\r\n };\r\n }\r\n\r\n /**\r\n * Add deduction (immutable)\r\n */\r\n static addDeduction(\r\n compensation: Compensation,\r\n deduction: Parameters<typeof this.createDeduction>[0]\r\n ): Compensation {\r\n return {\r\n ...compensation,\r\n deductions: [\r\n ...compensation.deductions,\r\n this.createDeduction(deduction, compensation.baseAmount),\r\n ],\r\n lastModified: new Date(),\r\n };\r\n }\r\n\r\n /**\r\n * Remove deduction (immutable)\r\n */\r\n static removeDeduction(\r\n compensation: Compensation,\r\n deductionType: Deduction['type']\r\n ): Compensation {\r\n return {\r\n ...compensation,\r\n deductions: compensation.deductions.filter((d) => d.type !== deductionType),\r\n lastModified: new Date(),\r\n };\r\n }\r\n\r\n /**\r\n * Calculate compensation breakdown\r\n */\r\n static calculateBreakdown(compensation: Compensation): CompensationBreakdownResult {\r\n const { baseAmount, allowances, deductions } = compensation;\r\n\r\n // Calculate actual amounts for percentage-based items\r\n const calculatedAllowances = allowances.map((a) => ({\r\n ...a,\r\n calculatedAmount: a.isPercentage && a.value !== undefined\r\n ? applyPercentage(baseAmount, a.value)\r\n : a.amount,\r\n }));\r\n\r\n const calculatedDeductions = deductions.map((d) => ({\r\n ...d,\r\n calculatedAmount: d.isPercentage && d.value !== undefined\r\n ? applyPercentage(baseAmount, d.value)\r\n : d.amount,\r\n }));\r\n\r\n const grossAmount = calculateGross(\r\n baseAmount,\r\n calculatedAllowances.map((a) => ({ amount: a.calculatedAmount }))\r\n );\r\n const netAmount = calculateNet(\r\n grossAmount,\r\n calculatedDeductions.map((d) => ({ amount: d.calculatedAmount }))\r\n );\r\n\r\n return {\r\n baseAmount,\r\n allowances: calculatedAllowances,\r\n deductions: calculatedDeductions,\r\n grossAmount,\r\n netAmount: Math.max(0, netAmount),\r\n };\r\n }\r\n\r\n /**\r\n * Apply salary increment (immutable)\r\n */\r\n static applyIncrement(\r\n compensation: Compensation,\r\n params: { percentage?: number; amount?: number; effectiveFrom?: Date }\r\n ): Compensation {\r\n const newBaseAmount = params.amount\r\n ? compensation.baseAmount + params.amount\r\n : compensation.baseAmount * (1 + (params.percentage || 0) / 100);\r\n\r\n return this.updateBaseAmount(\r\n compensation,\r\n Math.round(newBaseAmount),\r\n params.effectiveFrom\r\n );\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Compensation Builder\r\n// ============================================================================\r\n\r\nexport class CompensationBuilder {\r\n private data: CreateCompensationParams = {\r\n baseAmount: 0,\r\n frequency: 'monthly',\r\n currency: HRM_CONFIG.payroll.defaultCurrency,\r\n allowances: [],\r\n deductions: [],\r\n };\r\n\r\n /**\r\n * Set base amount\r\n */\r\n withBase(\r\n amount: number,\r\n frequency: PaymentFrequency = 'monthly',\r\n currency = HRM_CONFIG.payroll.defaultCurrency\r\n ): this {\r\n this.data.baseAmount = amount;\r\n this.data.frequency = frequency;\r\n this.data.currency = currency;\r\n return this;\r\n }\r\n\r\n /**\r\n * Add allowance\r\n */\r\n addAllowance(\r\n type: Allowance['type'],\r\n value: number,\r\n isPercentage = false,\r\n name?: string\r\n ): this {\r\n this.data.allowances = [\r\n ...(this.data.allowances || []),\r\n { type, value, isPercentage, name },\r\n ];\r\n return this;\r\n }\r\n\r\n /**\r\n * Add deduction\r\n */\r\n addDeduction(\r\n type: Deduction['type'],\r\n value: number,\r\n isPercentage = false,\r\n name?: string\r\n ): this {\r\n this.data.deductions = [\r\n ...(this.data.deductions || []),\r\n { type, value, isPercentage, name },\r\n ];\r\n return this;\r\n }\r\n\r\n /**\r\n * Set effective date\r\n */\r\n effectiveFrom(date: Date): this {\r\n this.data.effectiveFrom = date;\r\n return this;\r\n }\r\n\r\n /**\r\n * Build compensation\r\n */\r\n build(): Compensation {\r\n if (!this.data.baseAmount) {\r\n throw new Error('baseAmount is required');\r\n }\r\n return CompensationFactory.create(this.data);\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Compensation Presets\r\n// ============================================================================\r\n\r\nexport const CompensationPresets = {\r\n /**\r\n * Basic compensation (base only)\r\n */\r\n basic(baseAmount: number): Compensation {\r\n return new CompensationBuilder()\r\n .withBase(baseAmount)\r\n .build();\r\n },\r\n\r\n /**\r\n * With house rent allowance\r\n */\r\n withHouseRent(baseAmount: number, rentPercentage = 50): Compensation {\r\n return new CompensationBuilder()\r\n .withBase(baseAmount)\r\n .addAllowance('housing', rentPercentage, true, 'House Rent')\r\n .build();\r\n },\r\n\r\n /**\r\n * With medical allowance\r\n */\r\n withMedical(baseAmount: number, medicalPercentage = 10): Compensation {\r\n return new CompensationBuilder()\r\n .withBase(baseAmount)\r\n .addAllowance('medical', medicalPercentage, true, 'Medical Allowance')\r\n .build();\r\n },\r\n\r\n /**\r\n * Standard package (house rent + medical + transport)\r\n */\r\n standard(baseAmount: number): Compensation {\r\n return new CompensationBuilder()\r\n .withBase(baseAmount)\r\n .addAllowance('housing', 50, true, 'House Rent')\r\n .addAllowance('medical', 10, true, 'Medical Allowance')\r\n .addAllowance('transport', 5, true, 'Transport Allowance')\r\n .build();\r\n },\r\n\r\n /**\r\n * With provident fund\r\n */\r\n withProvidentFund(baseAmount: number, pfPercentage = 10): Compensation {\r\n return new CompensationBuilder()\r\n .withBase(baseAmount)\r\n .addAllowance('housing', 50, true, 'House Rent')\r\n .addAllowance('medical', 10, true, 'Medical Allowance')\r\n .addDeduction('provident_fund', pfPercentage, true, 'Provident Fund')\r\n .build();\r\n },\r\n\r\n /**\r\n * Executive package\r\n */\r\n executive(baseAmount: number): Compensation {\r\n return new CompensationBuilder()\r\n .withBase(baseAmount)\r\n .addAllowance('housing', 60, true, 'House Rent')\r\n .addAllowance('medical', 15, true, 'Medical Allowance')\r\n .addAllowance('transport', 10, true, 'Transport Allowance')\r\n .addAllowance('mobile', 5, true, 'Mobile Allowance')\r\n .addDeduction('provident_fund', 10, true, 'Provident Fund')\r\n .build();\r\n },\r\n};\r\n\r\n// ============================================================================\r\n// Factory Function\r\n// ============================================================================\r\n\r\n/**\r\n * Create new compensation builder\r\n */\r\nexport function createCompensation(): CompensationBuilder {\r\n return new CompensationBuilder();\r\n}\r\n\r\n// ============================================================================\r\n// Default Export\r\n// ============================================================================\r\n\r\nexport default {\r\n CompensationFactory,\r\n CompensationBuilder,\r\n CompensationPresets,\r\n createCompensation,\r\n};\r\n\r\n","/**\r\n * @classytic/payroll - Employee Plugin\r\n *\r\n * Mongoose plugin that adds HRM methods and virtuals to Employee schema\r\n */\r\n\r\nimport type { Schema, Document } from 'mongoose';\r\nimport type {\r\n EmployeeStatus,\r\n Compensation,\r\n TerminationReason,\r\n Allowance,\r\n Deduction,\r\n} from '../types.js';\r\nimport { diffInDays } from '../utils/date.js';\r\nimport { sumDeductions } from '../utils/calculation.js';\r\nimport { isActive, isTerminated } from '../utils/validation.js';\r\nimport { CompensationFactory } from '../factories/compensation.factory.js';\r\nimport { logger } from '../utils/logger.js';\r\n\r\n// ============================================================================\r\n// Plugin Options\r\n// ============================================================================\r\n\r\nexport interface EmployeePluginOptions {\r\n /** Require bank details for salary payment */\r\n requireBankDetails?: boolean;\r\n /** Field name for compensation */\r\n compensationField?: string;\r\n /** Field name for status */\r\n statusField?: string;\r\n /** Enable auto salary calculation on save */\r\n autoCalculateSalary?: boolean;\r\n}\r\n\r\n// ============================================================================\r\n// Employee Plugin\r\n// ============================================================================\r\n\r\n/**\r\n * Mongoose plugin that adds HRM functionality to Employee schema\r\n * \r\n * @example\r\n * const employeeSchema = new Schema({\r\n * ...employmentFields,\r\n * // Custom fields\r\n * });\r\n * \r\n * employeeSchema.plugin(employeePlugin);\r\n */\r\nexport function employeePlugin(\r\n schema: Schema,\r\n options: EmployeePluginOptions = {}\r\n): void {\r\n const {\r\n requireBankDetails = false,\r\n compensationField = 'compensation',\r\n statusField = 'status',\r\n autoCalculateSalary = true,\r\n } = options;\r\n\r\n // ========================================\r\n // Virtuals\r\n // ========================================\r\n\r\n /**\r\n * Virtual: Current net salary\r\n */\r\n schema.virtual('currentSalary').get(function (this: Document & Record<string, unknown>) {\r\n const compensation = this[compensationField] as Compensation | undefined;\r\n return compensation?.netSalary || 0;\r\n });\r\n\r\n /**\r\n * Virtual: Is active\r\n */\r\n schema.virtual('isActive').get(function (this: Document & Record<string, unknown>) {\r\n return isActive({ status: this[statusField] as EmployeeStatus });\r\n });\r\n\r\n /**\r\n * Virtual: Is terminated\r\n */\r\n schema.virtual('isTerminated').get(function (this: Document & Record<string, unknown>) {\r\n return isTerminated({ status: this[statusField] as EmployeeStatus });\r\n });\r\n\r\n /**\r\n * Virtual: Years of service\r\n */\r\n schema.virtual('yearsOfService').get(function (this: Document & Record<string, unknown>) {\r\n const hireDate = this.hireDate as Date | undefined;\r\n const terminationDate = this.terminationDate as Date | undefined;\r\n if (!hireDate) return 0;\r\n \r\n const end = terminationDate || new Date();\r\n const days = diffInDays(hireDate, end);\r\n return Math.max(0, Math.floor((days / 365.25) * 10) / 10);\r\n });\r\n\r\n /**\r\n * Virtual: Is on probation\r\n */\r\n schema.virtual('isOnProbation').get(function (this: Document & Record<string, unknown>) {\r\n const probationEndDate = this.probationEndDate as Date | undefined;\r\n if (!probationEndDate) return false;\r\n return new Date() < new Date(probationEndDate);\r\n });\r\n\r\n // ========================================\r\n // Methods\r\n // ========================================\r\n\r\n /**\r\n * Calculate salary breakdown\r\n */\r\n schema.methods.calculateSalary = function (this: Document & Record<string, unknown>) {\r\n const compensation = this[compensationField] as Compensation | undefined;\r\n if (!compensation) {\r\n return { gross: 0, deductions: 0, net: 0 };\r\n }\r\n\r\n const breakdown = CompensationFactory.calculateBreakdown(compensation);\r\n\r\n return {\r\n gross: breakdown.grossAmount,\r\n deductions: sumDeductions(\r\n breakdown.deductions.map((d) => ({ amount: d.calculatedAmount }))\r\n ),\r\n net: breakdown.netAmount,\r\n };\r\n };\r\n\r\n /**\r\n * Update salary calculations\r\n */\r\n schema.methods.updateSalaryCalculations = function (this: Document & Record<string, unknown>) {\r\n const compensation = this[compensationField] as Compensation | undefined;\r\n if (!compensation) return;\r\n\r\n const calculated = (this as unknown as { calculateSalary: () => { gross: number; net: number } }).calculateSalary();\r\n (this[compensationField] as Compensation).grossSalary = calculated.gross;\r\n (this[compensationField] as Compensation).netSalary = calculated.net;\r\n (this[compensationField] as Compensation).lastModified = new Date();\r\n };\r\n\r\n /**\r\n * Check if can receive salary\r\n */\r\n schema.methods.canReceiveSalary = function (this: Document & Record<string, unknown>): boolean {\r\n const status = this[statusField] as EmployeeStatus;\r\n const compensation = this[compensationField] as Compensation | undefined;\r\n const bankDetails = this.bankDetails as { accountNumber?: string } | undefined;\r\n\r\n return (\r\n status === 'active' &&\r\n (compensation?.baseAmount ?? 0) > 0 &&\r\n (!requireBankDetails || !!bankDetails?.accountNumber)\r\n );\r\n };\r\n\r\n /**\r\n * Add allowance\r\n */\r\n schema.methods.addAllowance = function (\r\n this: Document & Record<string, unknown>,\r\n type: Allowance['type'],\r\n amount: number,\r\n taxable = true\r\n ) {\r\n const compensation = this[compensationField] as Compensation;\r\n if (!compensation.allowances) {\r\n compensation.allowances = [];\r\n }\r\n compensation.allowances.push({\r\n type,\r\n name: type,\r\n amount,\r\n taxable,\r\n recurring: true,\r\n effectiveFrom: new Date(),\r\n });\r\n (this as unknown as { updateSalaryCalculations: () => void }).updateSalaryCalculations();\r\n };\r\n\r\n /**\r\n * Add deduction\r\n */\r\n schema.methods.addDeduction = function (\r\n this: Document & Record<string, unknown>,\r\n type: Deduction['type'],\r\n amount: number,\r\n auto = false,\r\n description = ''\r\n ) {\r\n const compensation = this[compensationField] as Compensation;\r\n if (!compensation.deductions) {\r\n compensation.deductions = [];\r\n }\r\n compensation.deductions.push({\r\n type,\r\n name: type,\r\n amount,\r\n auto,\r\n recurring: true,\r\n description,\r\n effectiveFrom: new Date(),\r\n });\r\n (this as unknown as { updateSalaryCalculations: () => void }).updateSalaryCalculations();\r\n };\r\n\r\n /**\r\n * Remove allowance\r\n */\r\n schema.methods.removeAllowance = function (\r\n this: Document & Record<string, unknown>,\r\n type: Allowance['type']\r\n ) {\r\n const compensation = this[compensationField] as Compensation;\r\n if (!compensation.allowances) return;\r\n compensation.allowances = compensation.allowances.filter((a) => a.type !== type);\r\n (this as unknown as { updateSalaryCalculations: () => void }).updateSalaryCalculations();\r\n };\r\n\r\n /**\r\n * Remove deduction\r\n */\r\n schema.methods.removeDeduction = function (\r\n this: Document & Record<string, unknown>,\r\n type: Deduction['type']\r\n ) {\r\n const compensation = this[compensationField] as Compensation;\r\n if (!compensation.deductions) return;\r\n compensation.deductions = compensation.deductions.filter((d) => d.type !== type);\r\n (this as unknown as { updateSalaryCalculations: () => void }).updateSalaryCalculations();\r\n };\r\n\r\n /**\r\n * Terminate employee\r\n */\r\n schema.methods.terminate = function (\r\n this: Document & Record<string, unknown>,\r\n reason: TerminationReason,\r\n terminationDate = new Date()\r\n ) {\r\n const status = this[statusField] as EmployeeStatus;\r\n if (status === 'terminated') {\r\n throw new Error('Employee already terminated');\r\n }\r\n\r\n const compensation = this[compensationField] as Compensation;\r\n const employmentHistory = (this.employmentHistory as unknown[]) || [];\r\n\r\n employmentHistory.push({\r\n hireDate: this.hireDate,\r\n terminationDate,\r\n reason,\r\n finalSalary: compensation?.netSalary || 0,\r\n position: this.position,\r\n department: this.department,\r\n });\r\n\r\n this[statusField] = 'terminated';\r\n this.terminationDate = terminationDate;\r\n this.employmentHistory = employmentHistory;\r\n\r\n logger.info('Employee terminated', {\r\n employeeId: this.employeeId,\r\n organizationId: this.organizationId?.toString(),\r\n reason,\r\n });\r\n };\r\n\r\n /**\r\n * Re-hire employee\r\n */\r\n schema.methods.reHire = function (\r\n this: Document & Record<string, unknown>,\r\n hireDate = new Date(),\r\n position?: string,\r\n department?: string\r\n ) {\r\n const status = this[statusField] as EmployeeStatus;\r\n if (status !== 'terminated') {\r\n throw new Error('Can only re-hire terminated employees');\r\n }\r\n\r\n this[statusField] = 'active';\r\n this.hireDate = hireDate;\r\n this.terminationDate = null;\r\n\r\n if (position) this.position = position;\r\n if (department) this.department = department;\r\n\r\n logger.info('Employee re-hired', {\r\n employeeId: this.employeeId,\r\n organizationId: this.organizationId?.toString(),\r\n });\r\n };\r\n\r\n // ========================================\r\n // Hooks\r\n // ========================================\r\n\r\n /**\r\n * Pre-save hook to update salary calculations\r\n * Mongoose v9 compatible - uses async without next callback\r\n */\r\n if (autoCalculateSalary) {\r\n schema.pre('save', async function () {\r\n if (this.isModified(compensationField)) {\r\n (this as unknown as { updateSalaryCalculations: () => void }).updateSalaryCalculations();\r\n }\r\n });\r\n }\r\n\r\n // ========================================\r\n // Indexes\r\n // ========================================\r\n\r\n schema.index({ organizationId: 1, employeeId: 1 }, { unique: true });\r\n schema.index({ userId: 1, organizationId: 1 }, { unique: true });\r\n schema.index({ organizationId: 1, status: 1 });\r\n schema.index({ organizationId: 1, department: 1 });\r\n schema.index({ organizationId: 1, 'compensation.netSalary': -1 });\r\n\r\n logger.debug('Employee plugin applied', {\r\n requireBankDetails,\r\n autoCalculateSalary,\r\n });\r\n}\r\n\r\nexport default employeePlugin;\r\n\r\n","/**\r\n * @classytic/payroll - Result Type\r\n *\r\n * Rust-inspired Result type for type-safe error handling\r\n * No more try/catch everywhere - explicit error handling\r\n */\r\n\r\n// ============================================================================\r\n// Result Type Definition\r\n// ============================================================================\r\n\r\n/** Success result */\r\nexport interface Ok<T> {\r\n readonly ok: true;\r\n readonly value: T;\r\n}\r\n\r\n/** Error result */\r\nexport interface Err<E> {\r\n readonly ok: false;\r\n readonly error: E;\r\n}\r\n\r\n/** Result type - either success or error */\r\nexport type Result<T, E = Error> = Ok<T> | Err<E>;\r\n\r\n// ============================================================================\r\n// Constructors\r\n// ============================================================================\r\n\r\n/**\r\n * Create a success result\r\n */\r\nexport function ok<T>(value: T): Ok<T> {\r\n return { ok: true, value };\r\n}\r\n\r\n/**\r\n * Create an error result\r\n */\r\nexport function err<E>(error: E): Err<E> {\r\n return { ok: false, error };\r\n}\r\n\r\n// ============================================================================\r\n// Type Guards\r\n// ============================================================================\r\n\r\n/**\r\n * Check if result is success\r\n */\r\nexport function isOk<T, E>(result: Result<T, E>): result is Ok<T> {\r\n return result.ok === true;\r\n}\r\n\r\n/**\r\n * Check if result is error\r\n */\r\nexport function isErr<T, E>(result: Result<T, E>): result is Err<E> {\r\n return result.ok === false;\r\n}\r\n\r\n// ============================================================================\r\n// Unwrap Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Unwrap result value or throw error\r\n */\r\nexport function unwrap<T, E>(result: Result<T, E>): T {\r\n if (isOk(result)) {\r\n return result.value;\r\n }\r\n throw result.error;\r\n}\r\n\r\n/**\r\n * Unwrap result value or return default\r\n */\r\nexport function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T {\r\n if (isOk(result)) {\r\n return result.value;\r\n }\r\n return defaultValue;\r\n}\r\n\r\n/**\r\n * Unwrap result value or compute default\r\n */\r\nexport function unwrapOrElse<T, E>(\r\n result: Result<T, E>,\r\n fn: (error: E) => T\r\n): T {\r\n if (isOk(result)) {\r\n return result.value;\r\n }\r\n return fn(result.error);\r\n}\r\n\r\n// ============================================================================\r\n// Transformation Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Map success value\r\n */\r\nexport function map<T, U, E>(\r\n result: Result<T, E>,\r\n fn: (value: T) => U\r\n): Result<U, E> {\r\n if (isOk(result)) {\r\n return ok(fn(result.value));\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * Map error value\r\n */\r\nexport function mapErr<T, E, F>(\r\n result: Result<T, E>,\r\n fn: (error: E) => F\r\n): Result<T, F> {\r\n if (isErr(result)) {\r\n return err(fn(result.error));\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * FlatMap (chain) success value\r\n */\r\nexport function flatMap<T, U, E>(\r\n result: Result<T, E>,\r\n fn: (value: T) => Result<U, E>\r\n): Result<U, E> {\r\n if (isOk(result)) {\r\n return fn(result.value);\r\n }\r\n return result;\r\n}\r\n\r\n// ============================================================================\r\n// Utility Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Try/catch wrapper for async functions\r\n */\r\nexport async function tryCatch<T, E = Error>(\r\n fn: () => Promise<T>,\r\n errorTransform?: (error: unknown) => E\r\n): Promise<Result<T, E>> {\r\n try {\r\n const value = await fn();\r\n return ok(value);\r\n } catch (error) {\r\n if (errorTransform) {\r\n return err(errorTransform(error));\r\n }\r\n return err(error as E);\r\n }\r\n}\r\n\r\n/**\r\n * Try/catch wrapper for sync functions\r\n */\r\nexport function tryCatchSync<T, E = Error>(\r\n fn: () => T,\r\n errorTransform?: (error: unknown) => E\r\n): Result<T, E> {\r\n try {\r\n const value = fn();\r\n return ok(value);\r\n } catch (error) {\r\n if (errorTransform) {\r\n return err(errorTransform(error));\r\n }\r\n return err(error as E);\r\n }\r\n}\r\n\r\n/**\r\n * Combine multiple results into one\r\n */\r\nexport function all<T, E>(results: Result<T, E>[]): Result<T[], E> {\r\n const values: T[] = [];\r\n for (const result of results) {\r\n if (isErr(result)) {\r\n return result;\r\n }\r\n values.push(result.value);\r\n }\r\n return ok(values);\r\n}\r\n\r\n/**\r\n * Pattern match on result\r\n */\r\nexport function match<T, E, R>(\r\n result: Result<T, E>,\r\n handlers: {\r\n ok: (value: T) => R;\r\n err: (error: E) => R;\r\n }\r\n): R {\r\n if (isOk(result)) {\r\n return handlers.ok(result.value);\r\n }\r\n return handlers.err(result.error);\r\n}\r\n\r\n/**\r\n * Convert Promise<Result> to Result<Promise>\r\n */\r\nexport async function fromPromise<T, E = Error>(\r\n promise: Promise<T>,\r\n errorTransform?: (error: unknown) => E\r\n): Promise<Result<T, E>> {\r\n return tryCatch(() => promise, errorTransform);\r\n}\r\n\r\n/**\r\n * Create Result from nullable value\r\n */\r\nexport function fromNullable<T, E>(\r\n value: T | null | undefined,\r\n error: E\r\n): Result<T, E> {\r\n if (value === null || value === undefined) {\r\n return err(error);\r\n }\r\n return ok(value);\r\n}\r\n\r\n// ============================================================================\r\n// Result Class (OOP Alternative)\r\n// ============================================================================\r\n\r\nexport class ResultClass<T, E = Error> {\r\n private constructor(private readonly result: Result<T, E>) {}\r\n\r\n static ok<T>(value: T): ResultClass<T, never> {\r\n return new ResultClass(ok(value));\r\n }\r\n\r\n static err<E>(error: E): ResultClass<never, E> {\r\n return new ResultClass(err(error));\r\n }\r\n\r\n static async fromAsync<T, E = Error>(\r\n fn: () => Promise<T>,\r\n errorTransform?: (error: unknown) => E\r\n ): Promise<ResultClass<T, E>> {\r\n const result = await tryCatch(fn, errorTransform);\r\n return new ResultClass(result);\r\n }\r\n\r\n isOk(): boolean {\r\n return isOk(this.result);\r\n }\r\n\r\n isErr(): boolean {\r\n return isErr(this.result);\r\n }\r\n\r\n unwrap(): T {\r\n return unwrap(this.result);\r\n }\r\n\r\n unwrapOr(defaultValue: T): T {\r\n return unwrapOr(this.result, defaultValue);\r\n }\r\n\r\n map<U>(fn: (value: T) => U): ResultClass<U, E> {\r\n return new ResultClass(map(this.result, fn));\r\n }\r\n\r\n mapErr<F>(fn: (error: E) => F): ResultClass<T, F> {\r\n return new ResultClass(mapErr(this.result, fn));\r\n }\r\n\r\n flatMap<U>(fn: (value: T) => Result<U, E>): ResultClass<U, E> {\r\n return new ResultClass(flatMap(this.result, fn));\r\n }\r\n\r\n match<R>(handlers: { ok: (value: T) => R; err: (error: E) => R }): R {\r\n return match(this.result, handlers);\r\n }\r\n\r\n toResult(): Result<T, E> {\r\n return this.result;\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Alias for convenience\r\n// ============================================================================\r\n\r\nexport const Result = {\r\n ok,\r\n err,\r\n isOk,\r\n isErr,\r\n unwrap,\r\n unwrapOr,\r\n unwrapOrElse,\r\n map,\r\n mapErr,\r\n flatMap,\r\n tryCatch,\r\n tryCatchSync,\r\n all,\r\n match,\r\n fromPromise,\r\n fromNullable,\r\n};\r\n\r\n","/**\r\n * @classytic/payroll - Payroll Factory\r\n *\r\n * Clean object creation for payroll records\r\n * Immutable operations and builder pattern\r\n */\r\n\r\nimport type {\r\n ObjectIdLike,\r\n PayrollBreakdown,\r\n PayrollPeriod,\r\n PaymentMethod,\r\n Allowance,\r\n Deduction,\r\n Compensation,\r\n} from '../types.js';\r\nimport { getPayPeriod } from '../utils/date.js';\r\nimport { calculateGross, calculateNet, sumAllowances, sumDeductions } from '../utils/calculation.js';\r\nimport { HRM_CONFIG } from '../config.js';\r\n\r\n// ============================================================================\r\n// Payroll Factory Types\r\n// ============================================================================\r\n\r\nexport interface CreatePayrollParams {\r\n employeeId: ObjectIdLike;\r\n organizationId: ObjectIdLike;\r\n baseAmount: number;\r\n allowances?: Array<{ type: string; amount: number; taxable?: boolean }>;\r\n deductions?: Array<{ type: string; amount: number; description?: string }>;\r\n period?: { month?: number; year?: number };\r\n metadata?: {\r\n currency?: string;\r\n paymentMethod?: PaymentMethod;\r\n notes?: string;\r\n };\r\n}\r\n\r\nexport interface PayrollData {\r\n employeeId: ObjectIdLike;\r\n organizationId: ObjectIdLike;\r\n period: PayrollPeriod;\r\n breakdown: PayrollBreakdown;\r\n status: 'pending';\r\n processedAt: null;\r\n paidAt: null;\r\n metadata: {\r\n currency: string;\r\n paymentMethod?: PaymentMethod;\r\n notes?: string;\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Payroll Factory\r\n// ============================================================================\r\n\r\nexport class PayrollFactory {\r\n /**\r\n * Create payroll data object\r\n */\r\n static create(params: CreatePayrollParams): PayrollData {\r\n const {\r\n employeeId,\r\n organizationId,\r\n baseAmount,\r\n allowances = [],\r\n deductions = [],\r\n period = {},\r\n metadata = {},\r\n } = params;\r\n\r\n const calculatedAllowances = this.calculateAllowances(baseAmount, allowances);\r\n const calculatedDeductions = this.calculateDeductions(baseAmount, deductions);\r\n\r\n const gross = calculateGross(baseAmount, calculatedAllowances);\r\n const net = calculateNet(gross, calculatedDeductions);\r\n\r\n return {\r\n employeeId,\r\n organizationId,\r\n period: this.createPeriod(period),\r\n breakdown: {\r\n baseAmount,\r\n allowances: calculatedAllowances,\r\n deductions: calculatedDeductions,\r\n grossSalary: gross,\r\n netSalary: net,\r\n },\r\n status: 'pending',\r\n processedAt: null,\r\n paidAt: null,\r\n metadata: {\r\n currency: metadata.currency || HRM_CONFIG.payroll.defaultCurrency,\r\n paymentMethod: metadata.paymentMethod,\r\n notes: metadata.notes,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Create pay period\r\n */\r\n static createPeriod(params: { month?: number; year?: number; payDate?: Date }): PayrollPeriod {\r\n const now = new Date();\r\n const month = params.month || now.getMonth() + 1;\r\n const year = params.year || now.getFullYear();\r\n const period = getPayPeriod(month, year);\r\n\r\n return {\r\n ...period,\r\n payDate: params.payDate || new Date(),\r\n };\r\n }\r\n\r\n /**\r\n * Calculate allowances from base amount\r\n */\r\n static calculateAllowances(\r\n baseAmount: number,\r\n allowances: Array<{ type: string; amount: number; taxable?: boolean; isPercentage?: boolean; value?: number }>\r\n ): Array<{ type: string; amount: number; taxable: boolean }> {\r\n return allowances.map((allowance) => {\r\n const amount =\r\n allowance.isPercentage && allowance.value !== undefined\r\n ? Math.round((baseAmount * allowance.value) / 100)\r\n : allowance.amount;\r\n\r\n return {\r\n type: allowance.type,\r\n amount,\r\n taxable: allowance.taxable ?? true,\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Calculate deductions from base amount\r\n */\r\n static calculateDeductions(\r\n baseAmount: number,\r\n deductions: Array<{ type: string; amount: number; description?: string; isPercentage?: boolean; value?: number }>\r\n ): Array<{ type: string; amount: number; description?: string }> {\r\n return deductions.map((deduction) => {\r\n const amount =\r\n deduction.isPercentage && deduction.value !== undefined\r\n ? Math.round((baseAmount * deduction.value) / 100)\r\n : deduction.amount;\r\n\r\n return {\r\n type: deduction.type,\r\n amount,\r\n description: deduction.description,\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Create bonus object\r\n */\r\n static createBonus(params: {\r\n type: string;\r\n amount: number;\r\n reason: string;\r\n approvedBy?: ObjectIdLike;\r\n }): { type: string; amount: number; reason: string; approvedBy?: ObjectIdLike; approvedAt: Date } {\r\n return {\r\n type: params.type,\r\n amount: params.amount,\r\n reason: params.reason,\r\n approvedBy: params.approvedBy,\r\n approvedAt: new Date(),\r\n };\r\n }\r\n\r\n /**\r\n * Mark payroll as paid (immutable)\r\n * Sets both top-level transactionId and metadata for compatibility\r\n */\r\n static markAsPaid<T extends { status: string; paidAt?: Date | null; processedAt?: Date | null; transactionId?: unknown; metadata?: Record<string, unknown> }>(\r\n payroll: T,\r\n params: { paidAt?: Date; transactionId?: ObjectIdLike; paymentMethod?: PaymentMethod } = {}\r\n ): T & { status: 'paid' } {\r\n return {\r\n ...payroll,\r\n status: 'paid' as const,\r\n paidAt: params.paidAt || new Date(),\r\n processedAt: payroll.processedAt || params.paidAt || new Date(),\r\n transactionId: params.transactionId || payroll.transactionId,\r\n metadata: {\r\n ...payroll.metadata,\r\n transactionId: params.transactionId,\r\n paymentMethod: params.paymentMethod || payroll.metadata?.paymentMethod,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Mark payroll as processed (immutable)\r\n */\r\n static markAsProcessed<T extends { status: string; processedAt: Date | null }>(\r\n payroll: T,\r\n params: { processedAt?: Date } = {}\r\n ): T & { status: 'processing' } {\r\n return {\r\n ...payroll,\r\n status: 'processing' as const,\r\n processedAt: params.processedAt || new Date(),\r\n };\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Payroll Builder\r\n// ============================================================================\r\n\r\nexport class PayrollBuilder {\r\n private data: Partial<CreatePayrollParams> = {\r\n allowances: [],\r\n deductions: [],\r\n period: {},\r\n metadata: {},\r\n };\r\n\r\n /**\r\n * Set employee ID\r\n */\r\n forEmployee(employeeId: ObjectIdLike): this {\r\n this.data.employeeId = employeeId;\r\n return this;\r\n }\r\n\r\n /**\r\n * Set organization ID\r\n */\r\n inOrganization(organizationId: ObjectIdLike): this {\r\n this.data.organizationId = organizationId;\r\n return this;\r\n }\r\n\r\n /**\r\n * Set base amount\r\n */\r\n withBaseAmount(amount: number): this {\r\n this.data.baseAmount = amount;\r\n return this;\r\n }\r\n\r\n /**\r\n * Set pay period\r\n */\r\n forPeriod(month: number, year: number): this {\r\n this.data.period = { month, year };\r\n return this;\r\n }\r\n\r\n /**\r\n * Add allowance\r\n */\r\n addAllowance(\r\n type: string,\r\n value: number,\r\n isPercentage = false,\r\n name?: string\r\n ): this {\r\n this.data.allowances = [\r\n ...(this.data.allowances || []),\r\n {\r\n type,\r\n amount: isPercentage ? 0 : value,\r\n isPercentage,\r\n value: isPercentage ? value : undefined,\r\n } as { type: string; amount: number },\r\n ];\r\n return this;\r\n }\r\n\r\n /**\r\n * Add deduction\r\n */\r\n addDeduction(\r\n type: string,\r\n value: number,\r\n isPercentage = false,\r\n description?: string\r\n ): this {\r\n this.data.deductions = [\r\n ...(this.data.deductions || []),\r\n {\r\n type,\r\n amount: isPercentage ? 0 : value,\r\n isPercentage,\r\n value: isPercentage ? value : undefined,\r\n description,\r\n } as { type: string; amount: number; description?: string },\r\n ];\r\n return this;\r\n }\r\n\r\n /**\r\n * Add bonus\r\n */\r\n addBonus(amount: number, reason: string): this {\r\n return this.addAllowance('bonus', amount, false, reason);\r\n }\r\n\r\n /**\r\n * Set currency\r\n */\r\n withCurrency(currency: string): this {\r\n this.data.metadata = { ...this.data.metadata, currency };\r\n return this;\r\n }\r\n\r\n /**\r\n * Set payment method\r\n */\r\n withPaymentMethod(method: PaymentMethod): this {\r\n this.data.metadata = { ...this.data.metadata, paymentMethod: method };\r\n return this;\r\n }\r\n\r\n /**\r\n * Set notes\r\n */\r\n withNotes(notes: string): this {\r\n this.data.metadata = { ...this.data.metadata, notes };\r\n return this;\r\n }\r\n\r\n /**\r\n * Build payroll data\r\n */\r\n build(): PayrollData {\r\n if (!this.data.employeeId || !this.data.organizationId) {\r\n throw new Error('employeeId and organizationId are required');\r\n }\r\n if (!this.data.baseAmount) {\r\n throw new Error('baseAmount is required');\r\n }\r\n\r\n return PayrollFactory.create(this.data as CreatePayrollParams);\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Batch Payroll Factory\r\n// ============================================================================\r\n\r\nexport class BatchPayrollFactory {\r\n /**\r\n * Create payroll records for multiple employees\r\n */\r\n static createBatch(\r\n employees: Array<{\r\n _id: ObjectIdLike;\r\n organizationId: ObjectIdLike;\r\n compensation: Compensation;\r\n }>,\r\n params: { month: number; year: number; organizationId?: ObjectIdLike }\r\n ): PayrollData[] {\r\n return employees.map((employee) =>\r\n PayrollFactory.create({\r\n employeeId: employee._id,\r\n organizationId: params.organizationId || employee.organizationId,\r\n baseAmount: employee.compensation.baseAmount,\r\n allowances: employee.compensation.allowances || [],\r\n deductions: employee.compensation.deductions || [],\r\n period: { month: params.month, year: params.year },\r\n metadata: { currency: employee.compensation.currency },\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * Calculate total payroll amounts\r\n */\r\n static calculateTotalPayroll(payrolls: Array<{ breakdown: PayrollBreakdown }>): {\r\n count: number;\r\n totalGross: number;\r\n totalNet: number;\r\n totalAllowances: number;\r\n totalDeductions: number;\r\n } {\r\n return payrolls.reduce(\r\n (totals, payroll) => ({\r\n count: totals.count + 1,\r\n totalGross: totals.totalGross + payroll.breakdown.grossSalary,\r\n totalNet: totals.totalNet + payroll.breakdown.netSalary,\r\n totalAllowances: totals.totalAllowances + sumAllowances(payroll.breakdown.allowances),\r\n totalDeductions: totals.totalDeductions + sumDeductions(payroll.breakdown.deductions),\r\n }),\r\n { count: 0, totalGross: 0, totalNet: 0, totalAllowances: 0, totalDeductions: 0 }\r\n );\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Factory Function\r\n// ============================================================================\r\n\r\n/**\r\n * Create new payroll builder\r\n */\r\nexport function createPayroll(): PayrollBuilder {\r\n return new PayrollBuilder();\r\n}\r\n\r\n// ============================================================================\r\n// Default Export\r\n// ============================================================================\r\n\r\nexport default {\r\n PayrollFactory,\r\n PayrollBuilder,\r\n BatchPayrollFactory,\r\n createPayroll,\r\n};\r\n\r\n","/**\r\n * @classytic/payroll - Employee Service\r\n *\r\n * High-level employee operations with dependency injection\r\n */\r\n\r\nimport type { Model, ClientSession } from 'mongoose';\r\nimport type {\r\n ObjectIdLike,\r\n EmployeeDocument,\r\n EmployeeStatus,\r\n Department,\r\n EmploymentType,\r\n Compensation,\r\n OperationContext,\r\n} from '../types.js';\r\nimport { EmployeeFactory, type CreateEmployeeParams } from '../factories/employee.factory.js';\r\nimport { employee as employeeQuery, toObjectId } from '../utils/query-builders.js';\r\nimport { isActive, isEmployed, canReceiveSalary } from '../utils/validation.js';\r\nimport { logger } from '../utils/logger.js';\r\n\r\n// ============================================================================\r\n// Employee Service\r\n// ============================================================================\r\n\r\nexport class EmployeeService {\r\n constructor(private readonly EmployeeModel: Model<EmployeeDocument>) {}\r\n\r\n /**\r\n * Find employee by ID\r\n */\r\n async findById(\r\n employeeId: ObjectIdLike,\r\n options: { session?: ClientSession; populate?: boolean } = {}\r\n ): Promise<EmployeeDocument | null> {\r\n let query = this.EmployeeModel.findById(toObjectId(employeeId));\r\n \r\n if (options.session) {\r\n query = query.session(options.session);\r\n }\r\n \r\n if (options.populate) {\r\n query = query.populate('userId', 'name email phone');\r\n }\r\n \r\n return query.exec();\r\n }\r\n\r\n /**\r\n * Find employee by user and organization\r\n */\r\n async findByUserId(\r\n userId: ObjectIdLike,\r\n organizationId: ObjectIdLike,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<EmployeeDocument | null> {\r\n const query = employeeQuery()\r\n .forUser(userId)\r\n .forOrganization(organizationId)\r\n .build();\r\n\r\n let mongooseQuery = this.EmployeeModel.findOne(query);\r\n \r\n if (options.session) {\r\n mongooseQuery = mongooseQuery.session(options.session);\r\n }\r\n \r\n return mongooseQuery.exec();\r\n }\r\n\r\n /**\r\n * Find active employees in organization\r\n */\r\n async findActive(\r\n organizationId: ObjectIdLike,\r\n options: { session?: ClientSession; projection?: Record<string, number> } = {}\r\n ): Promise<EmployeeDocument[]> {\r\n const query = employeeQuery()\r\n .forOrganization(organizationId)\r\n .active()\r\n .build();\r\n\r\n let mongooseQuery = this.EmployeeModel.find(query, options.projection);\r\n \r\n if (options.session) {\r\n mongooseQuery = mongooseQuery.session(options.session);\r\n }\r\n \r\n return mongooseQuery.exec();\r\n }\r\n\r\n /**\r\n * Find employed employees (not terminated)\r\n */\r\n async findEmployed(\r\n organizationId: ObjectIdLike,\r\n options: { session?: ClientSession; projection?: Record<string, number> } = {}\r\n ): Promise<EmployeeDocument[]> {\r\n const query = employeeQuery()\r\n .forOrganization(organizationId)\r\n .employed()\r\n .build();\r\n\r\n let mongooseQuery = this.EmployeeModel.find(query, options.projection);\r\n \r\n if (options.session) {\r\n mongooseQuery = mongooseQuery.session(options.session);\r\n }\r\n \r\n return mongooseQuery.exec();\r\n }\r\n\r\n /**\r\n * Find employees by department\r\n */\r\n async findByDepartment(\r\n organizationId: ObjectIdLike,\r\n department: Department,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<EmployeeDocument[]> {\r\n const query = employeeQuery()\r\n .forOrganization(organizationId)\r\n .inDepartment(department)\r\n .active()\r\n .build();\r\n\r\n let mongooseQuery = this.EmployeeModel.find(query);\r\n \r\n if (options.session) {\r\n mongooseQuery = mongooseQuery.session(options.session);\r\n }\r\n \r\n return mongooseQuery.exec();\r\n }\r\n\r\n /**\r\n * Find employees eligible for payroll\r\n */\r\n async findEligibleForPayroll(\r\n organizationId: ObjectIdLike,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<EmployeeDocument[]> {\r\n const query = employeeQuery()\r\n .forOrganization(organizationId)\r\n .employed()\r\n .build();\r\n\r\n let mongooseQuery = this.EmployeeModel.find(query);\r\n \r\n if (options.session) {\r\n mongooseQuery = mongooseQuery.session(options.session);\r\n }\r\n \r\n const employees = await mongooseQuery.exec();\r\n return employees.filter((emp) => canReceiveSalary(emp));\r\n }\r\n\r\n /**\r\n * Create new employee\r\n */\r\n async create(\r\n params: CreateEmployeeParams,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<EmployeeDocument> {\r\n const employeeData = EmployeeFactory.create(params);\r\n \r\n const [employee] = await this.EmployeeModel.create([employeeData], {\r\n session: options.session,\r\n });\r\n\r\n logger.info('Employee created', {\r\n employeeId: employee.employeeId,\r\n organizationId: employee.organizationId.toString(),\r\n });\r\n\r\n return employee;\r\n }\r\n\r\n /**\r\n * Update employee status\r\n */\r\n async updateStatus(\r\n employeeId: ObjectIdLike,\r\n status: EmployeeStatus,\r\n context: OperationContext = {},\r\n options: { session?: ClientSession } = {}\r\n ): Promise<EmployeeDocument> {\r\n const employee = await this.findById(employeeId, options);\r\n if (!employee) {\r\n throw new Error('Employee not found');\r\n }\r\n\r\n employee.status = status;\r\n await employee.save({ session: options.session });\r\n\r\n logger.info('Employee status updated', {\r\n employeeId: employee.employeeId,\r\n newStatus: status,\r\n });\r\n\r\n return employee;\r\n }\r\n\r\n /**\r\n * Update employee compensation\r\n * \r\n * NOTE: This merges the compensation fields rather than replacing the entire object.\r\n * To update allowances/deductions, use addAllowance/removeAllowance methods.\r\n */\r\n async updateCompensation(\r\n employeeId: ObjectIdLike,\r\n compensation: Partial<Compensation>,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<EmployeeDocument> {\r\n // First fetch the employee to get current compensation\r\n const currentEmployee = await this.EmployeeModel.findById(toObjectId(employeeId)).session(options.session || null);\r\n if (!currentEmployee) {\r\n throw new Error('Employee not found');\r\n }\r\n\r\n // Build update object that only sets provided fields\r\n const updateFields: Record<string, unknown> = {\r\n 'compensation.lastModified': new Date(),\r\n };\r\n\r\n // Only update specific fields if provided (preserve allowances/deductions)\r\n if (compensation.baseAmount !== undefined) {\r\n updateFields['compensation.baseAmount'] = compensation.baseAmount;\r\n }\r\n if (compensation.currency !== undefined) {\r\n updateFields['compensation.currency'] = compensation.currency;\r\n }\r\n if (compensation.frequency !== undefined) {\r\n updateFields['compensation.frequency'] = compensation.frequency;\r\n }\r\n if (compensation.effectiveFrom !== undefined) {\r\n updateFields['compensation.effectiveFrom'] = compensation.effectiveFrom;\r\n }\r\n // Note: allowances and deductions should NOT be updated here\r\n // Use addAllowance/removeAllowance methods instead\r\n\r\n const employee = await this.EmployeeModel.findByIdAndUpdate(\r\n toObjectId(employeeId),\r\n { $set: updateFields },\r\n { new: true, runValidators: true, session: options.session }\r\n );\r\n\r\n if (!employee) {\r\n throw new Error('Employee not found');\r\n }\r\n\r\n return employee;\r\n }\r\n\r\n /**\r\n * Get employee statistics for organization\r\n */\r\n async getEmployeeStats(\r\n organizationId: ObjectIdLike,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<{\r\n total: number;\r\n active: number;\r\n employed: number;\r\n canReceiveSalary: number;\r\n byStatus: Record<string, number>;\r\n byDepartment: Record<string, number>;\r\n }> {\r\n const query = employeeQuery().forOrganization(organizationId).build();\r\n \r\n let mongooseQuery = this.EmployeeModel.find(query);\r\n if (options.session) {\r\n mongooseQuery = mongooseQuery.session(options.session);\r\n }\r\n \r\n const employees = await mongooseQuery.exec();\r\n\r\n return {\r\n total: employees.length,\r\n active: employees.filter(isActive).length,\r\n employed: employees.filter(isEmployed).length,\r\n canReceiveSalary: employees.filter(canReceiveSalary).length,\r\n byStatus: this.groupByStatus(employees),\r\n byDepartment: this.groupByDepartment(employees),\r\n };\r\n }\r\n\r\n /**\r\n * Group employees by status\r\n */\r\n private groupByStatus(employees: EmployeeDocument[]): Record<string, number> {\r\n return employees.reduce(\r\n (acc, emp) => {\r\n acc[emp.status] = (acc[emp.status] || 0) + 1;\r\n return acc;\r\n },\r\n {} as Record<string, number>\r\n );\r\n }\r\n\r\n /**\r\n * Group employees by department\r\n */\r\n private groupByDepartment(employees: EmployeeDocument[]): Record<string, number> {\r\n return employees.reduce(\r\n (acc, emp) => {\r\n const dept = emp.department || 'unassigned';\r\n acc[dept] = (acc[dept] || 0) + 1;\r\n return acc;\r\n },\r\n {} as Record<string, number>\r\n );\r\n }\r\n\r\n /**\r\n * Check if employee is active\r\n */\r\n isActive(employee: EmployeeDocument): boolean {\r\n return isActive(employee);\r\n }\r\n\r\n /**\r\n * Check if employee is employed\r\n */\r\n isEmployed(employee: EmployeeDocument): boolean {\r\n return isEmployed(employee);\r\n }\r\n\r\n /**\r\n * Check if employee can receive salary\r\n */\r\n canReceiveSalary(employee: EmployeeDocument): boolean {\r\n return canReceiveSalary(employee);\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Factory Function\r\n// ============================================================================\r\n\r\n/**\r\n * Create employee service instance\r\n */\r\nexport function createEmployeeService(\r\n EmployeeModel: Model<EmployeeDocument>\r\n): EmployeeService {\r\n return new EmployeeService(EmployeeModel);\r\n}\r\n\r\n","/**\r\n * @classytic/payroll - Payroll Service\r\n *\r\n * High-level payroll operations with dependency injection\r\n */\r\n\r\nimport type { Model, ClientSession } from 'mongoose';\r\nimport type {\r\n ObjectIdLike,\r\n PayrollRecordDocument,\r\n EmployeeDocument,\r\n PayrollStatus,\r\n PaymentMethod,\r\n} from '../types.js';\r\nimport {\r\n PayrollFactory,\r\n BatchPayrollFactory,\r\n type PayrollData,\r\n} from '../factories/payroll.factory.js';\r\nimport { payroll as payrollQuery, toObjectId } from '../utils/query-builders.js';\r\nimport { getCurrentPeriod } from '../utils/date.js';\r\nimport { canReceiveSalary } from '../utils/validation.js';\r\nimport { logger } from '../utils/logger.js';\r\nimport type { EmployeeService } from './employee.service.js';\r\n\r\n// ============================================================================\r\n// Payroll Service\r\n// ============================================================================\r\n\r\nexport class PayrollService {\r\n constructor(\r\n private readonly PayrollModel: Model<PayrollRecordDocument>,\r\n private readonly employeeService: EmployeeService\r\n ) {}\r\n\r\n /**\r\n * Find payroll by ID\r\n */\r\n async findById(\r\n payrollId: ObjectIdLike,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<PayrollRecordDocument | null> {\r\n let query = this.PayrollModel.findById(toObjectId(payrollId));\r\n \r\n if (options.session) {\r\n query = query.session(options.session);\r\n }\r\n \r\n return query.exec();\r\n }\r\n\r\n /**\r\n * Find payrolls by employee\r\n */\r\n async findByEmployee(\r\n employeeId: ObjectIdLike,\r\n organizationId: ObjectIdLike,\r\n options: { session?: ClientSession; limit?: number } = {}\r\n ): Promise<PayrollRecordDocument[]> {\r\n const query = payrollQuery()\r\n .forEmployee(employeeId)\r\n .forOrganization(organizationId)\r\n .build();\r\n\r\n let mongooseQuery = this.PayrollModel.find(query)\r\n .sort({ 'period.year': -1, 'period.month': -1 })\r\n .limit(options.limit || 12);\r\n \r\n if (options.session) {\r\n mongooseQuery = mongooseQuery.session(options.session);\r\n }\r\n \r\n return mongooseQuery.exec();\r\n }\r\n\r\n /**\r\n * Find payrolls for a period\r\n */\r\n async findForPeriod(\r\n organizationId: ObjectIdLike,\r\n month: number,\r\n year: number,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<PayrollRecordDocument[]> {\r\n const query = payrollQuery()\r\n .forOrganization(organizationId)\r\n .forPeriod(month, year)\r\n .build();\r\n\r\n let mongooseQuery = this.PayrollModel.find(query);\r\n \r\n if (options.session) {\r\n mongooseQuery = mongooseQuery.session(options.session);\r\n }\r\n \r\n return mongooseQuery.exec();\r\n }\r\n\r\n /**\r\n * Find pending payrolls\r\n */\r\n async findPending(\r\n organizationId: ObjectIdLike,\r\n month: number,\r\n year: number,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<PayrollRecordDocument[]> {\r\n const query = payrollQuery()\r\n .forOrganization(organizationId)\r\n .forPeriod(month, year)\r\n .pending()\r\n .build();\r\n\r\n let mongooseQuery = this.PayrollModel.find(query);\r\n \r\n if (options.session) {\r\n mongooseQuery = mongooseQuery.session(options.session);\r\n }\r\n \r\n return mongooseQuery.exec();\r\n }\r\n\r\n /**\r\n * Find payroll by employee and period\r\n */\r\n async findByEmployeeAndPeriod(\r\n employeeId: ObjectIdLike,\r\n organizationId: ObjectIdLike,\r\n month: number,\r\n year: number,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<PayrollRecordDocument | null> {\r\n const query = payrollQuery()\r\n .forEmployee(employeeId)\r\n .forOrganization(organizationId)\r\n .forPeriod(month, year)\r\n .build();\r\n\r\n let mongooseQuery = this.PayrollModel.findOne(query);\r\n \r\n if (options.session) {\r\n mongooseQuery = mongooseQuery.session(options.session);\r\n }\r\n \r\n return mongooseQuery.exec();\r\n }\r\n\r\n /**\r\n * Create payroll record\r\n */\r\n async create(\r\n data: PayrollData,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<PayrollRecordDocument> {\r\n const [payroll] = await this.PayrollModel.create([data], {\r\n session: options.session,\r\n });\r\n\r\n logger.info('Payroll record created', {\r\n payrollId: payroll._id.toString(),\r\n employeeId: payroll.employeeId.toString(),\r\n });\r\n\r\n return payroll;\r\n }\r\n\r\n /**\r\n * Generate payroll for employee\r\n */\r\n async generateForEmployee(\r\n employeeId: ObjectIdLike,\r\n organizationId: ObjectIdLike,\r\n month: number,\r\n year: number,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<PayrollRecordDocument> {\r\n const employee = await this.employeeService.findById(employeeId, options);\r\n if (!employee) {\r\n throw new Error('Employee not found');\r\n }\r\n\r\n if (!canReceiveSalary(employee)) {\r\n throw new Error('Employee not eligible for payroll');\r\n }\r\n\r\n // Check if payroll already exists\r\n const existing = await this.findByEmployeeAndPeriod(\r\n employeeId,\r\n organizationId,\r\n month,\r\n year,\r\n options\r\n );\r\n if (existing) {\r\n throw new Error('Payroll already exists for this period');\r\n }\r\n\r\n const payrollData = PayrollFactory.create({\r\n employeeId,\r\n organizationId,\r\n baseAmount: employee.compensation.baseAmount,\r\n allowances: employee.compensation.allowances || [],\r\n deductions: employee.compensation.deductions || [],\r\n period: { month, year },\r\n metadata: { currency: employee.compensation.currency },\r\n });\r\n\r\n return this.create(payrollData, options);\r\n }\r\n\r\n /**\r\n * Generate batch payroll\r\n */\r\n async generateBatch(\r\n organizationId: ObjectIdLike,\r\n month: number,\r\n year: number,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<{\r\n success: boolean;\r\n generated: number;\r\n skipped: number;\r\n payrolls: PayrollRecordDocument[];\r\n message: string;\r\n }> {\r\n const employees = await this.employeeService.findEligibleForPayroll(\r\n organizationId,\r\n options\r\n );\r\n\r\n if (employees.length === 0) {\r\n return {\r\n success: true,\r\n generated: 0,\r\n skipped: 0,\r\n payrolls: [],\r\n message: 'No eligible employees',\r\n };\r\n }\r\n\r\n // Get existing payrolls\r\n const existingPayrolls = await this.findForPeriod(\r\n organizationId,\r\n month,\r\n year,\r\n options\r\n );\r\n const existingEmployeeIds = new Set(\r\n existingPayrolls.map((p) => p.employeeId.toString())\r\n );\r\n\r\n // Filter out employees who already have payroll\r\n const eligibleEmployees = employees.filter(\r\n (emp) => !existingEmployeeIds.has(emp._id.toString())\r\n );\r\n\r\n if (eligibleEmployees.length === 0) {\r\n return {\r\n success: true,\r\n generated: 0,\r\n skipped: employees.length,\r\n payrolls: [],\r\n message: 'Payrolls already exist for all employees',\r\n };\r\n }\r\n\r\n const payrollsData = BatchPayrollFactory.createBatch(eligibleEmployees, {\r\n month,\r\n year,\r\n organizationId,\r\n });\r\n\r\n const created = await this.PayrollModel.insertMany(payrollsData, {\r\n session: options.session,\r\n });\r\n\r\n logger.info('Batch payroll generated', {\r\n organizationId: organizationId.toString(),\r\n month,\r\n year,\r\n count: created.length,\r\n });\r\n\r\n return {\r\n success: true,\r\n generated: created.length,\r\n skipped: existingEmployeeIds.size,\r\n payrolls: created as PayrollRecordDocument[],\r\n message: `Generated ${created.length} payrolls`,\r\n };\r\n }\r\n\r\n /**\r\n * Mark payroll as paid\r\n */\r\n async markAsPaid(\r\n payrollId: ObjectIdLike,\r\n paymentDetails: {\r\n paidAt?: Date;\r\n transactionId?: ObjectIdLike;\r\n paymentMethod?: PaymentMethod;\r\n } = {},\r\n options: { session?: ClientSession } = {}\r\n ): Promise<PayrollRecordDocument> {\r\n const payroll = await this.findById(payrollId, options);\r\n if (!payroll) {\r\n throw new Error('Payroll not found');\r\n }\r\n\r\n if (payroll.status === 'paid') {\r\n throw new Error('Payroll already paid');\r\n }\r\n\r\n const payrollObj = payroll.toObject() as {\r\n status: string;\r\n paidAt: Date | null;\r\n processedAt: Date | null;\r\n metadata: Record<string, unknown>;\r\n };\r\n const updatedData = PayrollFactory.markAsPaid(payrollObj, paymentDetails);\r\n\r\n const updated = await this.PayrollModel.findByIdAndUpdate(\r\n payrollId,\r\n updatedData,\r\n { new: true, runValidators: true, session: options.session }\r\n );\r\n\r\n if (!updated) {\r\n throw new Error('Failed to update payroll');\r\n }\r\n\r\n logger.info('Payroll marked as paid', {\r\n payrollId: payrollId.toString(),\r\n });\r\n\r\n return updated;\r\n }\r\n\r\n /**\r\n * Mark payroll as processed\r\n */\r\n async markAsProcessed(\r\n payrollId: ObjectIdLike,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<PayrollRecordDocument> {\r\n const payroll = await this.findById(payrollId, options);\r\n if (!payroll) {\r\n throw new Error('Payroll not found');\r\n }\r\n\r\n const payrollObj = payroll.toObject() as { status: string; processedAt: Date | null };\r\n const updatedData = PayrollFactory.markAsProcessed(payrollObj);\r\n\r\n const updated = await this.PayrollModel.findByIdAndUpdate(\r\n payrollId,\r\n updatedData,\r\n { new: true, runValidators: true, session: options.session }\r\n );\r\n\r\n if (!updated) {\r\n throw new Error('Failed to update payroll');\r\n }\r\n\r\n return updated;\r\n }\r\n\r\n /**\r\n * Calculate period summary\r\n */\r\n async calculatePeriodSummary(\r\n organizationId: ObjectIdLike,\r\n month: number,\r\n year: number,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<{\r\n period: { month: number; year: number };\r\n count: number;\r\n totalGross: number;\r\n totalNet: number;\r\n totalAllowances: number;\r\n totalDeductions: number;\r\n byStatus: Record<string, number>;\r\n }> {\r\n const payrolls = await this.findForPeriod(organizationId, month, year, options);\r\n const summary = BatchPayrollFactory.calculateTotalPayroll(payrolls);\r\n\r\n return {\r\n period: { month, year },\r\n ...summary,\r\n byStatus: this.groupByStatus(payrolls),\r\n };\r\n }\r\n\r\n /**\r\n * Get employee payroll history\r\n */\r\n async getEmployeePayrollHistory(\r\n employeeId: ObjectIdLike,\r\n organizationId: ObjectIdLike,\r\n limit = 12,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<PayrollRecordDocument[]> {\r\n return this.findByEmployee(employeeId, organizationId, { ...options, limit });\r\n }\r\n\r\n /**\r\n * Get overview stats\r\n */\r\n async getOverviewStats(\r\n organizationId: ObjectIdLike,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<{\r\n currentPeriod: { month: number; year: number };\r\n count: number;\r\n totalGross: number;\r\n totalNet: number;\r\n totalAllowances: number;\r\n totalDeductions: number;\r\n byStatus: Record<string, number>;\r\n }> {\r\n const { month, year } = getCurrentPeriod();\r\n const result = await this.calculatePeriodSummary(organizationId, month, year, options);\r\n return {\r\n currentPeriod: result.period,\r\n count: result.count,\r\n totalGross: result.totalGross,\r\n totalNet: result.totalNet,\r\n totalAllowances: result.totalAllowances,\r\n totalDeductions: result.totalDeductions,\r\n byStatus: result.byStatus,\r\n };\r\n }\r\n\r\n /**\r\n * Group payrolls by status\r\n */\r\n private groupByStatus(payrolls: PayrollRecordDocument[]): Record<string, number> {\r\n return payrolls.reduce(\r\n (acc, payroll) => {\r\n acc[payroll.status] = (acc[payroll.status] || 0) + 1;\r\n return acc;\r\n },\r\n {} as Record<string, number>\r\n );\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Factory Function\r\n// ============================================================================\r\n\r\n/**\r\n * Create payroll service instance\r\n */\r\nexport function createPayrollService(\r\n PayrollModel: Model<PayrollRecordDocument>,\r\n employeeService: EmployeeService\r\n): PayrollService {\r\n return new PayrollService(PayrollModel, employeeService);\r\n}\r\n\r\n","/**\r\n * @classytic/payroll - Compensation Service\r\n *\r\n * High-level compensation operations with dependency injection\r\n */\r\n\r\nimport type { Model, ClientSession } from 'mongoose';\r\nimport type {\r\n ObjectIdLike,\r\n EmployeeDocument,\r\n Compensation,\r\n Allowance,\r\n Deduction,\r\n Department,\r\n CompensationBreakdownResult,\r\n} from '../types.js';\r\nimport {\r\n CompensationFactory,\r\n CompensationPresets,\r\n} from '../factories/compensation.factory.js';\r\nimport { toObjectId } from '../utils/query-builders.js';\r\nimport { logger } from '../utils/logger.js';\r\n\r\n// ============================================================================\r\n// Compensation Service\r\n// ============================================================================\r\n\r\nexport class CompensationService {\r\n constructor(private readonly EmployeeModel: Model<EmployeeDocument>) {}\r\n\r\n /**\r\n * Get employee compensation\r\n */\r\n async getEmployeeCompensation(\r\n employeeId: ObjectIdLike,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<Compensation> {\r\n let query = this.EmployeeModel.findById(toObjectId(employeeId));\r\n \r\n if (options.session) {\r\n query = query.session(options.session);\r\n }\r\n \r\n const employee = await query.exec();\r\n if (!employee) {\r\n throw new Error('Employee not found');\r\n }\r\n\r\n return employee.compensation;\r\n }\r\n\r\n /**\r\n * Calculate compensation breakdown\r\n */\r\n async calculateBreakdown(\r\n employeeId: ObjectIdLike,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<CompensationBreakdownResult> {\r\n const compensation = await this.getEmployeeCompensation(employeeId, options);\r\n return CompensationFactory.calculateBreakdown(compensation);\r\n }\r\n\r\n /**\r\n * Update base amount\r\n */\r\n async updateBaseAmount(\r\n employeeId: ObjectIdLike,\r\n newAmount: number,\r\n effectiveFrom = new Date(),\r\n options: { session?: ClientSession } = {}\r\n ): Promise<CompensationBreakdownResult> {\r\n const employee = await this.findEmployee(employeeId, options);\r\n\r\n const updatedCompensation = CompensationFactory.updateBaseAmount(\r\n employee.compensation,\r\n newAmount,\r\n effectiveFrom\r\n );\r\n\r\n employee.compensation = updatedCompensation;\r\n await employee.save({ session: options.session });\r\n\r\n logger.info('Compensation base amount updated', {\r\n employeeId: employee.employeeId,\r\n newAmount,\r\n });\r\n\r\n return this.calculateBreakdown(employeeId, options);\r\n }\r\n\r\n /**\r\n * Apply salary increment\r\n */\r\n async applyIncrement(\r\n employeeId: ObjectIdLike,\r\n params: { percentage?: number; amount?: number; effectiveFrom?: Date },\r\n options: { session?: ClientSession } = {}\r\n ): Promise<CompensationBreakdownResult> {\r\n const employee = await this.findEmployee(employeeId, options);\r\n const previousAmount = employee.compensation.baseAmount;\r\n\r\n const updatedCompensation = CompensationFactory.applyIncrement(\r\n employee.compensation,\r\n params\r\n );\r\n\r\n employee.compensation = updatedCompensation;\r\n await employee.save({ session: options.session });\r\n\r\n logger.info('Salary increment applied', {\r\n employeeId: employee.employeeId,\r\n previousAmount,\r\n newAmount: updatedCompensation.baseAmount,\r\n percentage: params.percentage,\r\n });\r\n\r\n return this.calculateBreakdown(employeeId, options);\r\n }\r\n\r\n /**\r\n * Add allowance\r\n */\r\n async addAllowance(\r\n employeeId: ObjectIdLike,\r\n allowance: {\r\n type: Allowance['type'];\r\n value: number;\r\n isPercentage?: boolean;\r\n name?: string;\r\n taxable?: boolean;\r\n },\r\n options: { session?: ClientSession } = {}\r\n ): Promise<CompensationBreakdownResult> {\r\n const employee = await this.findEmployee(employeeId, options);\r\n\r\n const updatedCompensation = CompensationFactory.addAllowance(\r\n employee.compensation,\r\n allowance\r\n );\r\n\r\n employee.compensation = updatedCompensation;\r\n await employee.save({ session: options.session });\r\n\r\n logger.info('Allowance added', {\r\n employeeId: employee.employeeId,\r\n type: allowance.type,\r\n value: allowance.value,\r\n });\r\n\r\n return this.calculateBreakdown(employeeId, options);\r\n }\r\n\r\n /**\r\n * Remove allowance\r\n */\r\n async removeAllowance(\r\n employeeId: ObjectIdLike,\r\n allowanceType: Allowance['type'],\r\n options: { session?: ClientSession } = {}\r\n ): Promise<CompensationBreakdownResult> {\r\n const employee = await this.findEmployee(employeeId, options);\r\n\r\n const updatedCompensation = CompensationFactory.removeAllowance(\r\n employee.compensation,\r\n allowanceType\r\n );\r\n\r\n employee.compensation = updatedCompensation;\r\n await employee.save({ session: options.session });\r\n\r\n logger.info('Allowance removed', {\r\n employeeId: employee.employeeId,\r\n type: allowanceType,\r\n });\r\n\r\n return this.calculateBreakdown(employeeId, options);\r\n }\r\n\r\n /**\r\n * Add deduction\r\n */\r\n async addDeduction(\r\n employeeId: ObjectIdLike,\r\n deduction: {\r\n type: Deduction['type'];\r\n value: number;\r\n isPercentage?: boolean;\r\n name?: string;\r\n auto?: boolean;\r\n },\r\n options: { session?: ClientSession } = {}\r\n ): Promise<CompensationBreakdownResult> {\r\n const employee = await this.findEmployee(employeeId, options);\r\n\r\n const updatedCompensation = CompensationFactory.addDeduction(\r\n employee.compensation,\r\n deduction\r\n );\r\n\r\n employee.compensation = updatedCompensation;\r\n await employee.save({ session: options.session });\r\n\r\n logger.info('Deduction added', {\r\n employeeId: employee.employeeId,\r\n type: deduction.type,\r\n value: deduction.value,\r\n });\r\n\r\n return this.calculateBreakdown(employeeId, options);\r\n }\r\n\r\n /**\r\n * Remove deduction\r\n */\r\n async removeDeduction(\r\n employeeId: ObjectIdLike,\r\n deductionType: Deduction['type'],\r\n options: { session?: ClientSession } = {}\r\n ): Promise<CompensationBreakdownResult> {\r\n const employee = await this.findEmployee(employeeId, options);\r\n\r\n const updatedCompensation = CompensationFactory.removeDeduction(\r\n employee.compensation,\r\n deductionType\r\n );\r\n\r\n employee.compensation = updatedCompensation;\r\n await employee.save({ session: options.session });\r\n\r\n logger.info('Deduction removed', {\r\n employeeId: employee.employeeId,\r\n type: deductionType,\r\n });\r\n\r\n return this.calculateBreakdown(employeeId, options);\r\n }\r\n\r\n /**\r\n * Set standard compensation\r\n */\r\n async setStandardCompensation(\r\n employeeId: ObjectIdLike,\r\n baseAmount: number,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<CompensationBreakdownResult> {\r\n const employee = await this.findEmployee(employeeId, options);\r\n\r\n employee.compensation = CompensationPresets.standard(baseAmount);\r\n await employee.save({ session: options.session });\r\n\r\n logger.info('Standard compensation set', {\r\n employeeId: employee.employeeId,\r\n baseAmount,\r\n });\r\n\r\n return this.calculateBreakdown(employeeId, options);\r\n }\r\n\r\n /**\r\n * Compare compensation between two employees\r\n */\r\n async compareCompensation(\r\n employeeId1: ObjectIdLike,\r\n employeeId2: ObjectIdLike,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<{\r\n employee1: CompensationBreakdownResult;\r\n employee2: CompensationBreakdownResult;\r\n difference: { base: number; gross: number; net: number };\r\n ratio: { base: number; gross: number; net: number };\r\n }> {\r\n const breakdown1 = await this.calculateBreakdown(employeeId1, options);\r\n const breakdown2 = await this.calculateBreakdown(employeeId2, options);\r\n\r\n return {\r\n employee1: breakdown1,\r\n employee2: breakdown2,\r\n difference: {\r\n base: breakdown2.baseAmount - breakdown1.baseAmount,\r\n gross: breakdown2.grossAmount - breakdown1.grossAmount,\r\n net: breakdown2.netAmount - breakdown1.netAmount,\r\n },\r\n ratio: {\r\n base: breakdown1.baseAmount > 0 ? breakdown2.baseAmount / breakdown1.baseAmount : 0,\r\n gross: breakdown1.grossAmount > 0 ? breakdown2.grossAmount / breakdown1.grossAmount : 0,\r\n net: breakdown1.netAmount > 0 ? breakdown2.netAmount / breakdown1.netAmount : 0,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Get department compensation stats\r\n */\r\n async getDepartmentCompensationStats(\r\n organizationId: ObjectIdLike,\r\n department: Department,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<{\r\n department: string;\r\n employeeCount: number;\r\n totalBase: number;\r\n totalGross: number;\r\n totalNet: number;\r\n averageBase: number;\r\n averageGross: number;\r\n averageNet: number;\r\n }> {\r\n let query = this.EmployeeModel.find({\r\n organizationId: toObjectId(organizationId),\r\n department,\r\n status: { $in: ['active', 'on_leave'] },\r\n });\r\n\r\n if (options.session) {\r\n query = query.session(options.session);\r\n }\r\n\r\n const employees = await query.exec();\r\n\r\n const breakdowns = employees.map((emp) =>\r\n CompensationFactory.calculateBreakdown(emp.compensation)\r\n );\r\n\r\n const totals = breakdowns.reduce(\r\n (acc, breakdown) => ({\r\n totalBase: acc.totalBase + breakdown.baseAmount,\r\n totalGross: acc.totalGross + breakdown.grossAmount,\r\n totalNet: acc.totalNet + breakdown.netAmount,\r\n }),\r\n { totalBase: 0, totalGross: 0, totalNet: 0 }\r\n );\r\n\r\n const count = employees.length || 1;\r\n\r\n return {\r\n department,\r\n employeeCount: employees.length,\r\n ...totals,\r\n averageBase: Math.round(totals.totalBase / count),\r\n averageGross: Math.round(totals.totalGross / count),\r\n averageNet: Math.round(totals.totalNet / count),\r\n };\r\n }\r\n\r\n /**\r\n * Get organization compensation stats\r\n */\r\n async getOrganizationCompensationStats(\r\n organizationId: ObjectIdLike,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<{\r\n employeeCount: number;\r\n totalBase: number;\r\n totalGross: number;\r\n totalNet: number;\r\n averageBase: number;\r\n averageGross: number;\r\n averageNet: number;\r\n byDepartment: Record<string, { count: number; totalNet: number }>;\r\n }> {\r\n let query = this.EmployeeModel.find({\r\n organizationId: toObjectId(organizationId),\r\n status: { $in: ['active', 'on_leave'] },\r\n });\r\n\r\n if (options.session) {\r\n query = query.session(options.session);\r\n }\r\n\r\n const employees = await query.exec();\r\n\r\n const breakdowns = employees.map((emp) =>\r\n CompensationFactory.calculateBreakdown(emp.compensation)\r\n );\r\n\r\n const totals = breakdowns.reduce(\r\n (acc, breakdown) => ({\r\n totalBase: acc.totalBase + breakdown.baseAmount,\r\n totalGross: acc.totalGross + breakdown.grossAmount,\r\n totalNet: acc.totalNet + breakdown.netAmount,\r\n }),\r\n { totalBase: 0, totalGross: 0, totalNet: 0 }\r\n );\r\n\r\n const byDepartment: Record<string, { count: number; totalNet: number }> = {};\r\n employees.forEach((emp, i) => {\r\n const dept = emp.department || 'unassigned';\r\n if (!byDepartment[dept]) {\r\n byDepartment[dept] = { count: 0, totalNet: 0 };\r\n }\r\n byDepartment[dept].count++;\r\n byDepartment[dept].totalNet += breakdowns[i].netAmount;\r\n });\r\n\r\n const count = employees.length || 1;\r\n\r\n return {\r\n employeeCount: employees.length,\r\n ...totals,\r\n averageBase: Math.round(totals.totalBase / count),\r\n averageGross: Math.round(totals.totalGross / count),\r\n averageNet: Math.round(totals.totalNet / count),\r\n byDepartment,\r\n };\r\n }\r\n\r\n /**\r\n * Find employee helper\r\n */\r\n private async findEmployee(\r\n employeeId: ObjectIdLike,\r\n options: { session?: ClientSession } = {}\r\n ): Promise<EmployeeDocument> {\r\n let query = this.EmployeeModel.findById(toObjectId(employeeId));\r\n \r\n if (options.session) {\r\n query = query.session(options.session);\r\n }\r\n \r\n const employee = await query.exec();\r\n if (!employee) {\r\n throw new Error('Employee not found');\r\n }\r\n return employee;\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Factory Function\r\n// ============================================================================\r\n\r\n/**\r\n * Create compensation service instance\r\n */\r\nexport function createCompensationService(\r\n EmployeeModel: Model<EmployeeDocument>\r\n): CompensationService {\r\n return new CompensationService(EmployeeModel);\r\n}\r\n\r\n","/**\r\n * @classytic/payroll - Attendance Integration\r\n *\r\n * Native integration with @classytic/clockin.\r\n * ClockIn is a peer dependency - attendance is core to payroll.\r\n */\r\n\r\nimport type { Model } from 'mongoose';\r\nimport type { AttendanceInput } from './core/config.js';\r\n\r\n/**\r\n * ClockIn attendance shape (from @classytic/clockin)\r\n * \r\n * ClockIn stores one document per employee per month with:\r\n * - totalWorkDays: Total days worked\r\n * - fullDaysCount: Full work days\r\n * - halfDaysCount: Half days (counted as 0.5)\r\n * - paidLeaveDaysCount: Paid leave\r\n */\r\ninterface ClockInAttendance {\r\n tenantId: any;\r\n targetId: any;\r\n targetModel: string;\r\n year: number;\r\n month: number;\r\n monthlyTotal: number;\r\n uniqueDaysVisited: number;\r\n fullDaysCount: number;\r\n halfDaysCount: number;\r\n paidLeaveDaysCount: number;\r\n overtimeDaysCount: number;\r\n totalWorkDays: number;\r\n}\r\n\r\n/**\r\n * Get attendance for payroll calculation\r\n *\r\n * @example\r\n * ```typescript\r\n * import { getAttendance } from '@classytic/payroll';\r\n *\r\n * const attendance = await getAttendance(Attendance, {\r\n * organizationId: org._id,\r\n * employeeId: emp._id,\r\n * month: 3,\r\n * year: 2024,\r\n * expectedDays: 22,\r\n * });\r\n *\r\n * await payroll.processSalary({ employeeId, month: 3, year: 2024, attendance });\r\n * ```\r\n */\r\nexport async function getAttendance(\r\n AttendanceModel: Model<any>,\r\n params: {\r\n organizationId: any;\r\n employeeId: any;\r\n month: number;\r\n year: number;\r\n expectedDays: number;\r\n }\r\n): Promise<(AttendanceInput & { absentDays: number; overtimeDays: number }) | null> {\r\n const record = await AttendanceModel.findOne({\r\n tenantId: params.organizationId,\r\n targetId: params.employeeId,\r\n targetModel: 'Employee',\r\n year: params.year,\r\n month: params.month,\r\n }).lean<ClockInAttendance>();\r\n\r\n if (!record) return null;\r\n\r\n // Calculate actual days worked\r\n const fullDays = record.fullDaysCount || 0;\r\n const halfDays = (record.halfDaysCount || 0) * 0.5;\r\n const paidLeave = record.paidLeaveDaysCount || 0;\r\n const actualDays = Math.round(fullDays + halfDays + paidLeave);\r\n const absentDays = Math.max(0, params.expectedDays - actualDays);\r\n const overtimeDays = record.overtimeDaysCount || 0;\r\n\r\n return {\r\n expectedDays: params.expectedDays,\r\n actualDays,\r\n absentDays,\r\n overtimeDays,\r\n };\r\n}\r\n\r\n/**\r\n * Get attendance for multiple employees (efficient batch operation)\r\n *\r\n * @example\r\n * ```typescript\r\n * const attendanceMap = await batchGetAttendance(Attendance, {\r\n * organizationId: org._id,\r\n * employeeIds: [emp1._id, emp2._id, emp3._id],\r\n * month: 3,\r\n * year: 2024,\r\n * expectedDays: 22,\r\n * });\r\n *\r\n * const emp1Attendance = attendanceMap.get(emp1._id.toString());\r\n * ```\r\n */\r\nexport async function batchGetAttendance(\r\n AttendanceModel: Model<any>,\r\n params: {\r\n organizationId: any;\r\n employeeIds: any[];\r\n month: number;\r\n year: number;\r\n expectedDays: number;\r\n }\r\n): Promise<Map<string, AttendanceInput>> {\r\n const records = await AttendanceModel.find({\r\n tenantId: params.organizationId,\r\n targetId: { $in: params.employeeIds },\r\n targetModel: 'Employee',\r\n year: params.year,\r\n month: params.month,\r\n }).lean<ClockInAttendance[]>();\r\n\r\n const map = new Map<string, AttendanceInput>();\r\n\r\n for (const record of records) {\r\n const fullDays = record.fullDaysCount || 0;\r\n const halfDays = (record.halfDaysCount || 0) * 0.5;\r\n const paidLeave = record.paidLeaveDaysCount || 0;\r\n const actualDays = Math.round(fullDays + halfDays + paidLeave);\r\n\r\n map.set(record.targetId.toString(), {\r\n expectedDays: params.expectedDays,\r\n actualDays,\r\n });\r\n }\r\n\r\n return map;\r\n}\r\n\r\n","/**\r\n * @classytic/payroll - Holiday Management\r\n *\r\n * Simple holiday storage and retrieval.\r\n * ONE way to manage holidays - no confusion.\r\n */\r\n\r\nimport { Schema, type Model } from 'mongoose';\r\n\r\n/**\r\n * Holiday document\r\n */\r\nexport interface Holiday {\r\n organizationId?: any;\r\n date: Date;\r\n name: string;\r\n type: 'public' | 'company' | 'religious';\r\n paid: boolean;\r\n}\r\n\r\n/**\r\n * Create holiday schema\r\n *\r\n * @example\r\n * ```typescript\r\n * import { createHolidaySchema } from '@classytic/payroll';\r\n *\r\n * // Multi-tenant\r\n * const Holiday = model('Holiday', createHolidaySchema());\r\n *\r\n * // Single-tenant\r\n * const Holiday = model('Holiday', createHolidaySchema({ singleTenant: true }));\r\n * ```\r\n */\r\nexport function createHolidaySchema(options: {\r\n singleTenant?: boolean;\r\n} = {}): Schema {\r\n const fields: any = {\r\n date: { type: Date, required: true, index: true },\r\n name: { type: String, required: true },\r\n type: { \r\n type: String, \r\n enum: ['public', 'company', 'religious'], \r\n default: 'company' \r\n },\r\n paid: { type: Boolean, default: true },\r\n };\r\n\r\n if (!options.singleTenant) {\r\n fields.organizationId = {\r\n type: Schema.Types.ObjectId,\r\n ref: 'Organization',\r\n required: true,\r\n index: true,\r\n };\r\n }\r\n\r\n const schema = new Schema(fields, { timestamps: true });\r\n\r\n // Indexes\r\n if (!options.singleTenant) {\r\n schema.index({ organizationId: 1, date: 1 });\r\n } else {\r\n schema.index({ date: 1 });\r\n }\r\n\r\n return schema;\r\n}\r\n\r\n/**\r\n * Get holidays for a period\r\n *\r\n * @example\r\n * ```typescript\r\n * const holidays = await getHolidays(Holiday, {\r\n * organizationId: org._id, // optional for single-tenant\r\n * startDate: new Date('2024-03-01'),\r\n * endDate: new Date('2024-03-31'),\r\n * });\r\n * ```\r\n */\r\nexport async function getHolidays(\r\n HolidayModel: Model<any>,\r\n params: {\r\n organizationId?: any;\r\n startDate: Date;\r\n endDate: Date;\r\n }\r\n): Promise<Date[]> {\r\n const query: any = {\r\n date: { $gte: params.startDate, $lte: params.endDate },\r\n };\r\n\r\n if (params.organizationId) {\r\n query.organizationId = params.organizationId;\r\n }\r\n\r\n const holidays = await HolidayModel.find(query).select('date').lean();\r\n return holidays.map((h: { date: Date }) => h.date);\r\n}\r\n\r\n","/**\r\n * @classytic/payroll\r\n *\r\n * Enterprise-grade HRM and Payroll Management for MongoDB/Mongoose\r\n * Clean, pluggable, multi-tenant architecture\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\n// ============================================================================\r\n// Main Entry Point\r\n// ============================================================================\r\n\r\nexport {\r\n Payroll,\r\n PayrollBuilder,\r\n createPayrollInstance,\r\n getPayroll,\r\n resetPayroll,\r\n payroll as payrollInstance,\r\n} from './payroll.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport type {\r\n // Core Types\r\n ObjectIdLike,\r\n PayrollInitConfig,\r\n HRMConfig,\r\n SingleTenantConfig,\r\n OperationContext,\r\n PayrollInstance,\r\n Logger,\r\n DeepPartial,\r\n\r\n // Enums as Types\r\n EmploymentType,\r\n EmployeeStatus,\r\n Department,\r\n PaymentFrequency,\r\n AllowanceType,\r\n DeductionType,\r\n PayrollStatus,\r\n TerminationReason,\r\n HRMTransactionCategory,\r\n\r\n // Data Types\r\n Allowance,\r\n Deduction,\r\n Compensation,\r\n WorkSchedule,\r\n BankDetails,\r\n EmploymentHistoryEntry,\r\n PayrollStats,\r\n PayrollPeriod,\r\n PayrollBreakdown,\r\n\r\n // Document Types\r\n EmployeeDocument,\r\n PayrollRecordDocument,\r\n\r\n // Operation Types\r\n HireEmployeeParams,\r\n UpdateEmploymentParams,\r\n TerminateEmployeeParams,\r\n ReHireEmployeeParams,\r\n ListEmployeesParams,\r\n UpdateSalaryParams,\r\n AddAllowanceParams,\r\n RemoveAllowanceParams,\r\n AddDeductionParams,\r\n RemoveDeductionParams,\r\n UpdateBankDetailsParams,\r\n ProcessSalaryParams,\r\n ProcessBulkPayrollParams,\r\n PayrollHistoryParams,\r\n PayrollSummaryParams,\r\n ExportPayrollParams,\r\n ProcessSalaryResult,\r\n BulkPayrollResult,\r\n PayrollSummaryResult,\r\n} from './types.js';\r\n\r\n// ============================================================================\r\n// Enums / Constants\r\n// ============================================================================\r\n\r\nexport {\r\n EMPLOYMENT_TYPE,\r\n EMPLOYEE_STATUS,\r\n DEPARTMENT,\r\n PAYMENT_FREQUENCY,\r\n ALLOWANCE_TYPE,\r\n DEDUCTION_TYPE,\r\n PAYROLL_STATUS,\r\n TERMINATION_REASON,\r\n HRM_TRANSACTION_CATEGORIES,\r\n} from './enums.js';\r\n\r\n// ============================================================================\r\n// Configuration\r\n// ============================================================================\r\n\r\nexport {\r\n HRM_CONFIG,\r\n mergeConfig,\r\n calculateTax,\r\n determineOrgRole,\r\n} from './config.js';\r\n\r\n// ============================================================================\r\n// Schemas\r\n// ============================================================================\r\n\r\nexport {\r\n allowanceSchema,\r\n deductionSchema,\r\n compensationSchema,\r\n workScheduleSchema,\r\n bankDetailsSchema,\r\n employmentHistorySchema,\r\n payrollStatsSchema,\r\n employmentFields,\r\n} from './schemas/index.js';\r\n\r\n// ============================================================================\r\n// Models\r\n// ============================================================================\r\n\r\nexport {\r\n payrollRecordSchema,\r\n getPayrollRecordModel,\r\n type PayrollRecordModel,\r\n} from './models/index.js';\r\n\r\n// ============================================================================\r\n// Plugins\r\n// ============================================================================\r\n\r\nexport {\r\n employeePlugin,\r\n type EmployeePluginOptions,\r\n} from './plugins/index.js';\r\n\r\n// ============================================================================\r\n// Core\r\n// ============================================================================\r\n\r\nexport {\r\n // Result Type\r\n ok,\r\n err,\r\n isOk,\r\n isErr,\r\n unwrap,\r\n unwrapOr,\r\n map,\r\n mapErr,\r\n type Result,\r\n type Ok,\r\n type Err,\r\n\r\n // Events\r\n createEventBus,\r\n type PayrollEventMap,\r\n type EventBus,\r\n\r\n // Plugins\r\n PluginManager,\r\n type PayrollPluginDefinition,\r\n type PluginContext,\r\n\r\n // Container\r\n Container,\r\n initializeContainer,\r\n type ModelsContainer,\r\n type ContainerConfig,\r\n} from './core/index.js';\r\n\r\n// ============================================================================\r\n// Errors\r\n// ============================================================================\r\n\r\nexport {\r\n PayrollError,\r\n NotInitializedError,\r\n EmployeeNotFoundError,\r\n DuplicatePayrollError,\r\n NotEligibleError,\r\n EmployeeTerminatedError,\r\n ValidationError,\r\n} from './errors/index.js';\r\n\r\n// ============================================================================\r\n// Factories\r\n// ============================================================================\r\n\r\nexport {\r\n // Employee Factory\r\n EmployeeFactory,\r\n EmployeeBuilder,\r\n\r\n // Payroll Factory\r\n PayrollFactory,\r\n BatchPayrollFactory,\r\n\r\n // Compensation Factory\r\n CompensationFactory,\r\n CompensationBuilder,\r\n} from './factories/index.js';\r\n\r\n// ============================================================================\r\n// Services\r\n// ============================================================================\r\n\r\nexport {\r\n EmployeeService,\r\n PayrollService,\r\n CompensationService,\r\n} from './services/index.js';\r\n\r\n// ============================================================================\r\n// Utilities\r\n// ============================================================================\r\n\r\nexport {\r\n // Date Utilities\r\n addDays,\r\n addMonths,\r\n addYears,\r\n startOfMonth,\r\n endOfMonth,\r\n startOfYear,\r\n endOfYear,\r\n diffInDays,\r\n diffInMonths,\r\n getPayPeriod,\r\n getCurrentPeriod,\r\n isDateInRange,\r\n formatDateForDB,\r\n getWorkingDaysInMonth,\r\n\r\n // Calculation Utilities\r\n sum,\r\n sumBy,\r\n calculateGross,\r\n calculateNet,\r\n sumAllowances,\r\n sumDeductions,\r\n applyPercentage,\r\n calculateProRating,\r\n pipe,\r\n compose,\r\n\r\n // Validation Utilities\r\n isActive,\r\n isTerminated,\r\n isOnProbation,\r\n isEmployed,\r\n canReceiveSalary,\r\n createValidator,\r\n required,\r\n min,\r\n max,\r\n inRange,\r\n oneOf,\r\n\r\n // Query Builders\r\n QueryBuilder,\r\n EmployeeQueryBuilder,\r\n PayrollQueryBuilder,\r\n employee,\r\n payroll,\r\n toObjectId,\r\n} from './utils/index.js';\r\n\r\n// ============================================================================\r\n// Logger\r\n// ============================================================================\r\n\r\nexport {\r\n logger,\r\n getLogger,\r\n setLogger,\r\n enableLogging,\r\n disableLogging,\r\n isLoggingEnabled,\r\n} from './utils/logger.js';\r\n\r\n// ============================================================================\r\n// Attendance (ClockIn integration)\r\n// ============================================================================\r\n\r\nexport {\r\n getAttendance,\r\n batchGetAttendance,\r\n} from './attendance.js';\r\n\r\n// ============================================================================\r\n// Holidays\r\n// ============================================================================\r\n\r\nexport {\r\n createHolidaySchema,\r\n getHolidays,\r\n type Holiday,\r\n} from './holidays.js';\r\n\r\n// ============================================================================\r\n// Default Export\r\n// ============================================================================\r\n\r\nimport { payroll as payrollDefault } from './payroll.js';\r\nexport default payrollDefault;\r\n\r\n"]}
|