@classytic/payroll 1.0.2 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of @classytic/payroll might be problematic. Click here for more details.

Files changed (78) hide show
  1. package/README.md +2599 -574
  2. package/dist/calculators/index.d.ts +433 -0
  3. package/dist/calculators/index.js +283 -0
  4. package/dist/calculators/index.js.map +1 -0
  5. package/dist/core/index.d.ts +314 -0
  6. package/dist/core/index.js +1166 -0
  7. package/dist/core/index.js.map +1 -0
  8. package/dist/employee-identity-DXhgOgXE.d.ts +473 -0
  9. package/dist/employee.factory-BlZqhiCk.d.ts +189 -0
  10. package/dist/idempotency-Cw2CWicb.d.ts +52 -0
  11. package/dist/index.d.ts +902 -0
  12. package/dist/index.js +9108 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/jurisdiction/index.d.ts +660 -0
  15. package/dist/jurisdiction/index.js +533 -0
  16. package/dist/jurisdiction/index.js.map +1 -0
  17. package/dist/payroll.d.ts +429 -0
  18. package/dist/payroll.js +5192 -0
  19. package/dist/payroll.js.map +1 -0
  20. package/dist/schemas/index.d.ts +3262 -0
  21. package/dist/schemas/index.js +780 -0
  22. package/dist/schemas/index.js.map +1 -0
  23. package/dist/services/index.d.ts +582 -0
  24. package/dist/services/index.js +2172 -0
  25. package/dist/services/index.js.map +1 -0
  26. package/dist/shift-compliance/index.d.ts +1171 -0
  27. package/dist/shift-compliance/index.js +1479 -0
  28. package/dist/shift-compliance/index.js.map +1 -0
  29. package/dist/types-BN3K_Uhr.d.ts +1842 -0
  30. package/dist/utils/index.d.ts +893 -0
  31. package/dist/utils/index.js +1515 -0
  32. package/dist/utils/index.js.map +1 -0
  33. package/package.json +72 -37
  34. package/dist/types/config.d.ts +0 -162
  35. package/dist/types/core/compensation.manager.d.ts +0 -54
  36. package/dist/types/core/employment.manager.d.ts +0 -49
  37. package/dist/types/core/payroll.manager.d.ts +0 -60
  38. package/dist/types/enums.d.ts +0 -117
  39. package/dist/types/factories/compensation.factory.d.ts +0 -196
  40. package/dist/types/factories/employee.factory.d.ts +0 -149
  41. package/dist/types/factories/payroll.factory.d.ts +0 -319
  42. package/dist/types/hrm.orchestrator.d.ts +0 -47
  43. package/dist/types/index.d.ts +0 -20
  44. package/dist/types/init.d.ts +0 -30
  45. package/dist/types/models/payroll-record.model.d.ts +0 -3
  46. package/dist/types/plugins/employee.plugin.d.ts +0 -2
  47. package/dist/types/schemas/employment.schema.d.ts +0 -959
  48. package/dist/types/services/compensation.service.d.ts +0 -94
  49. package/dist/types/services/employee.service.d.ts +0 -28
  50. package/dist/types/services/payroll.service.d.ts +0 -30
  51. package/dist/types/utils/calculation.utils.d.ts +0 -26
  52. package/dist/types/utils/date.utils.d.ts +0 -35
  53. package/dist/types/utils/logger.d.ts +0 -12
  54. package/dist/types/utils/query-builders.d.ts +0 -83
  55. package/dist/types/utils/validation.utils.d.ts +0 -33
  56. package/payroll.d.ts +0 -241
  57. package/src/config.js +0 -177
  58. package/src/core/compensation.manager.js +0 -242
  59. package/src/core/employment.manager.js +0 -224
  60. package/src/core/payroll.manager.js +0 -499
  61. package/src/enums.js +0 -141
  62. package/src/factories/compensation.factory.js +0 -198
  63. package/src/factories/employee.factory.js +0 -173
  64. package/src/factories/payroll.factory.js +0 -413
  65. package/src/hrm.orchestrator.js +0 -139
  66. package/src/index.js +0 -172
  67. package/src/init.js +0 -62
  68. package/src/models/payroll-record.model.js +0 -126
  69. package/src/plugins/employee.plugin.js +0 -164
  70. package/src/schemas/employment.schema.js +0 -126
  71. package/src/services/compensation.service.js +0 -231
  72. package/src/services/employee.service.js +0 -162
  73. package/src/services/payroll.service.js +0 -213
  74. package/src/utils/calculation.utils.js +0 -91
  75. package/src/utils/date.utils.js +0 -120
  76. package/src/utils/logger.js +0 -36
  77. package/src/utils/query-builders.js +0 -185
  78. package/src/utils/validation.utils.js +0 -122
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/calculation.ts","../../src/core/config.ts","../../src/calculators/prorating.calculator.ts","../../src/calculators/attendance.calculator.ts","../../src/calculators/salary.calculator.ts"],"names":["periodWorkingDays"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @classytic/payroll - Calculation Utilities\n *\n * Pure, functional, composable financial calculations\n * No side effects, highly testable\n */\n\nimport type {\n Allowance,\n Deduction,\n Compensation,\n TaxCalculationResult,\n CompensationBreakdownResult,\n ProRatingResult,\n PayPeriodInfo,\n} from '../types.js';\nimport { diffInDays } from './date.js';\n\n// ============================================================================\n// Basic Math Operations\n// ============================================================================\n\n/**\n * Sum array of numbers\n */\nexport function sum(numbers: number[]): number {\n return numbers.reduce((total, n) => total + n, 0);\n}\n\n/**\n * Sum by property\n */\nexport function sumBy<T>(items: T[], getter: (item: T) => number): number {\n return items.reduce((total, item) => total + getter(item), 0);\n}\n\n/**\n * Sum allowances\n */\nexport function sumAllowances(allowances: Array<{ amount: number }>): number {\n return sumBy(allowances, (a) => a.amount);\n}\n\n/**\n * Sum deductions\n */\nexport function sumDeductions(deductions: Array<{ amount: number }>): number {\n return sumBy(deductions, (d) => d.amount);\n}\n\n/**\n * Apply percentage to amount\n */\nexport function applyPercentage(amount: number, percentage: number): number {\n return Math.round(amount * (percentage / 100));\n}\n\n/**\n * Calculate percentage of total\n */\nexport function calculatePercentage(part: number, total: number): number {\n return total > 0 ? Math.round((part / total) * 100) : 0;\n}\n\n/**\n * Round to decimal places\n */\nexport function roundTo(value: number, decimals = 2): number {\n const factor = Math.pow(10, decimals);\n return Math.round(value * factor) / factor;\n}\n\n// ============================================================================\n// Salary Calculations\n// ============================================================================\n\n/**\n * Calculate gross salary from base and allowances\n */\nexport function calculateGross(\n baseAmount: number,\n allowances: Array<{ amount: number }>\n): number {\n return baseAmount + sumAllowances(allowances);\n}\n\n/**\n * Calculate net salary from gross and deductions\n */\nexport function calculateNet(\n gross: number,\n deductions: Array<{ amount: number }>\n): number {\n return Math.max(0, gross - sumDeductions(deductions));\n}\n\n/**\n * Calculate total compensation\n */\nexport function calculateTotalCompensation(\n baseAmount: number,\n allowances: Array<{ amount: number }>,\n deductions: Array<{ amount: number }>\n): { gross: number; net: number; deductions: number } {\n const gross = calculateGross(baseAmount, allowances);\n const totalDeductions = sumDeductions(deductions);\n const net = calculateNet(gross, deductions);\n return { gross, net, deductions: totalDeductions };\n}\n\n// ============================================================================\n// Allowance & Deduction Calculation\n// ============================================================================\n\n/**\n * Calculate allowance amount (handles percentage-based)\n */\nexport function calculateAllowanceAmount(\n allowance: Pick<Allowance, 'amount' | 'isPercentage' | 'value'>,\n baseAmount: number\n): number {\n if (allowance.isPercentage && allowance.value !== undefined) {\n return applyPercentage(baseAmount, allowance.value);\n }\n return allowance.amount;\n}\n\n/**\n * Calculate deduction amount (handles percentage-based)\n */\nexport function calculateDeductionAmount(\n deduction: Pick<Deduction, 'amount' | 'isPercentage' | 'value'>,\n baseAmount: number\n): number {\n if (deduction.isPercentage && deduction.value !== undefined) {\n return applyPercentage(baseAmount, deduction.value);\n }\n return deduction.amount;\n}\n\n/**\n * Calculate all allowances with their actual amounts\n */\nexport function calculateAllowances(\n allowances: Allowance[],\n baseAmount: number\n): Array<Allowance & { calculatedAmount: number }> {\n return allowances.map((allowance) => ({\n ...allowance,\n calculatedAmount: calculateAllowanceAmount(allowance, baseAmount),\n }));\n}\n\n/**\n * Calculate all deductions with their actual amounts\n */\nexport function calculateDeductions(\n deductions: Deduction[],\n baseAmount: number\n): Array<Deduction & { calculatedAmount: number }> {\n return deductions.map((deduction) => ({\n ...deduction,\n calculatedAmount: calculateDeductionAmount(deduction, baseAmount),\n }));\n}\n\n// ============================================================================\n// Compensation Breakdown\n// ============================================================================\n\n/**\n * Calculate full compensation breakdown\n */\nexport function calculateCompensationBreakdown(\n compensation: Pick<Compensation, 'baseAmount' | 'allowances' | 'deductions'>\n): CompensationBreakdownResult {\n const { baseAmount, allowances = [], deductions = [] } = compensation;\n\n const calculatedAllowances = calculateAllowances(allowances, baseAmount);\n const calculatedDeductions = calculateDeductions(deductions, baseAmount);\n\n const grossAmount =\n baseAmount + sumBy(calculatedAllowances, (a) => a.calculatedAmount);\n const netAmount =\n grossAmount - sumBy(calculatedDeductions, (d) => d.calculatedAmount);\n\n return {\n baseAmount,\n allowances: calculatedAllowances,\n deductions: calculatedDeductions,\n grossAmount,\n netAmount: Math.max(0, netAmount),\n };\n}\n\n// ============================================================================\n// Pro-Rating Calculations\n// ============================================================================\n\n/**\n * Calculate pro-rating for mid-month hires\n */\nexport function calculateProRating(\n hireDate: Date,\n periodStart: Date,\n periodEnd: Date\n): ProRatingResult {\n const totalDays = diffInDays(periodStart, periodEnd) + 1;\n\n // Hired before period start - no pro-rating\n if (hireDate <= periodStart) {\n return {\n isProRated: false,\n totalDays,\n actualDays: totalDays,\n ratio: 1,\n };\n }\n\n // Hired during the period - pro-rate\n if (hireDate > periodStart && hireDate <= periodEnd) {\n const actualDays = diffInDays(hireDate, periodEnd) + 1;\n const ratio = actualDays / totalDays;\n\n return {\n isProRated: true,\n totalDays,\n actualDays,\n ratio,\n };\n }\n\n // Hired after period - no work days\n return {\n isProRated: false,\n totalDays,\n actualDays: 0,\n ratio: 0,\n };\n}\n\n/**\n * Apply pro-rating to an amount\n */\nexport function applyProRating(\n amount: number,\n proRating: ProRatingResult\n): number {\n return Math.round(amount * proRating.ratio);\n}\n\n/**\n * Calculate pro-rated salary\n */\nexport function calculateProRatedSalary(\n baseAmount: number,\n hireDate: Date,\n period: PayPeriodInfo\n): { amount: number; proRating: ProRatingResult } {\n const proRating = calculateProRating(hireDate, period.startDate, period.endDate);\n const amount = applyProRating(baseAmount, proRating);\n return { amount, proRating };\n}\n\n// ============================================================================\n// Tax Calculations\n// ============================================================================\n\n/**\n * Apply tax brackets to calculate tax\n */\nexport function applyTaxBrackets(\n amount: number,\n brackets: Array<{ min: number; max: number; rate: number }>\n): number {\n let tax = 0;\n\n for (const bracket of brackets) {\n if (amount > bracket.min) {\n const taxableAmount = Math.min(amount, bracket.max) - bracket.min;\n tax += taxableAmount * bracket.rate;\n }\n }\n\n return Math.round(tax);\n}\n\n/**\n * Calculate tax with result\n */\nexport function calculateTax(\n amount: number,\n brackets: Array<{ min: number; max: number; rate: number }>\n): TaxCalculationResult {\n const tax = applyTaxBrackets(amount, brackets);\n return {\n gross: amount,\n tax,\n net: amount - tax,\n };\n}\n\n// ============================================================================\n// Functional Composition\n// ============================================================================\n\n/**\n * Pipe functions left-to-right\n * pipe(f, g, h)(x) === h(g(f(x)))\n */\nexport function pipe<T>(...fns: Array<(value: T) => T>): (value: T) => T {\n return (value: T) => fns.reduce((acc, fn) => fn(acc), value);\n}\n\n/**\n * Compose functions right-to-left\n * compose(f, g, h)(x) === f(g(h(x)))\n */\nexport function compose<T>(...fns: Array<(value: T) => T>): (value: T) => T {\n return (value: T) => fns.reduceRight((acc, fn) => fn(acc), value);\n}\n\n/**\n * Create an allowance calculator factory\n */\nexport function createAllowanceCalculator(\n allowances: Allowance[]\n): (baseSalary: number) => Array<Allowance & { calculatedAmount: number }> {\n return (baseSalary: number) => calculateAllowances(allowances, baseSalary);\n}\n\n/**\n * Create a deduction calculator factory\n */\nexport function createDeductionCalculator(\n deductions: Deduction[]\n): (baseSalary: number) => Array<Deduction & { calculatedAmount: number }> {\n return (baseSalary: number) => calculateDeductions(deductions, baseSalary);\n}\n\n// ============================================================================\n// Overtime Calculations\n// ============================================================================\n\n/**\n * Calculate overtime pay\n */\nexport function calculateOvertime(\n hourlyRate: number,\n overtimeHours: number,\n multiplier = 1.5\n): number {\n return Math.round(hourlyRate * overtimeHours * multiplier);\n}\n\n/**\n * Calculate hourly rate from monthly salary\n */\nexport function calculateHourlyRate(\n monthlySalary: number,\n hoursPerMonth = 176 // 44 hours/week * 4 weeks\n): number {\n return Math.round(monthlySalary / hoursPerMonth);\n}\n\n/**\n * Calculate daily rate from monthly salary\n */\nexport function calculateDailyRate(\n monthlySalary: number,\n daysPerMonth = 22\n): number {\n return Math.round(monthlySalary / daysPerMonth);\n}\n\n// ============================================================================\n// Default Export\n// ============================================================================\n\nexport default {\n sum,\n sumBy,\n sumAllowances,\n sumDeductions,\n applyPercentage,\n calculatePercentage,\n roundTo,\n calculateGross,\n calculateNet,\n calculateTotalCompensation,\n calculateAllowanceAmount,\n calculateDeductionAmount,\n calculateAllowances,\n calculateDeductions,\n calculateCompensationBreakdown,\n calculateProRating,\n applyProRating,\n calculateProRatedSalary,\n applyTaxBrackets,\n calculateTax,\n pipe,\n compose,\n createAllowanceCalculator,\n createDeductionCalculator,\n calculateOvertime,\n calculateHourlyRate,\n calculateDailyRate,\n};\n\n","/**\n * @classytic/payroll - Configuration & Calculation Utilities\n *\n * DESIGN PRINCIPLES:\n * 1. Accept data, don't manage it\n * 2. Pure functions - easy to test, no side effects\n * 3. Smart defaults that work out of the box\n * 4. Override at operation time when needed\n *\n * The payroll package CALCULATES, it doesn't STORE calendars/holidays.\n * Your app manages that data and passes it when needed.\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Work schedule configuration */\nexport interface WorkSchedule {\n /** Working days (0=Sun, 1=Mon, ..., 6=Sat). Default: Mon-Fri */\n workingDays: number[];\n /** Hours per work day. Default: 8 */\n hoursPerDay: number;\n}\n\n/** Options passed when processing payroll */\nexport interface PayrollProcessingOptions {\n /** Holidays in this period (from YOUR app's holiday model) */\n holidays?: Date[];\n /** Override work schedule for this operation */\n workSchedule?: Partial<WorkSchedule>;\n /** Skip tax calculation */\n skipTax?: boolean;\n /** Skip proration (pay full amount regardless of hire/termination date) */\n skipProration?: boolean;\n /** Skip attendance deduction */\n skipAttendance?: boolean;\n}\n\n/** Working days calculation result */\nexport interface WorkingDaysResult {\n /** Total calendar days in period */\n totalDays: number;\n /** Working days (excluding weekends and holidays) */\n workingDays: number;\n /** Weekend days */\n weekends: number;\n /** Holiday count */\n holidays: number;\n}\n\n/** Proration calculation result */\nexport interface ProrationResult {\n /** Proration ratio (0-1) */\n ratio: number;\n /** Reason for proration */\n reason: 'full' | 'new_hire' | 'termination' | 'both';\n /** Whether salary should be prorated */\n isProrated: boolean;\n}\n\n/** Tax calculation result */\nexport interface TaxResult {\n /** Tax amount */\n amount: number;\n /** Effective tax rate */\n effectiveRate: number;\n}\n\n/** Attendance data (from YOUR attendance system) */\nexport interface AttendanceInput {\n /** Expected work days in period */\n expectedDays: number;\n /** Actual days worked */\n actualDays: number;\n}\n\n/** Complete salary calculation result */\nexport interface SalaryCalculationResult {\n /** Original base salary */\n baseSalary: number;\n /** Prorated base salary */\n proratedBase: number;\n /** Total allowances */\n totalAllowances: number;\n /** Total deductions (excluding tax) */\n totalDeductions: number;\n /** Attendance deduction */\n attendanceDeduction: number;\n /** Gross salary (prorated base + allowances) */\n grossSalary: number;\n /** Tax amount */\n taxAmount: number;\n /** Net salary (gross - all deductions - tax) */\n netSalary: number;\n /** Proration details */\n proration: ProrationResult;\n /** Working days details */\n workingDays: WorkingDaysResult;\n /** Itemized breakdown */\n breakdown: {\n allowances: Array<{ type: string; amount: number; taxable: boolean }>;\n deductions: Array<{ type: string; amount: number }>;\n };\n}\n\n// ============================================================================\n// Default Configuration\n// ============================================================================\n\n/**\n * Default tax brackets (US federal example)\n * For multi-jurisdiction support, use the jurisdiction system instead\n */\nexport const DEFAULT_TAX_BRACKETS: Array<{ min: number; max: number; rate: number }> = [\n { min: 0, max: 10000, rate: 0.10 },\n { min: 10000, max: 40000, rate: 0.12 },\n { min: 40000, max: 85000, rate: 0.22 },\n { min: 85000, max: 165000, rate: 0.24 },\n { min: 165000, max: 215000, rate: 0.32 },\n { min: 215000, max: 540000, rate: 0.35 },\n { min: 540000, max: Infinity, rate: 0.37 },\n];\n\nexport const DEFAULT_WORK_SCHEDULE: WorkSchedule = {\n workingDays: [1, 2, 3, 4, 5], // Monday to Friday\n hoursPerDay: 8,\n};\n\n// ============================================================================\n// Pure Calculation Functions\n// ============================================================================\n\n/**\n * Count working days in a date range\n *\n * @example\n * const result = countWorkingDays(\n * new Date('2024-03-01'),\n * new Date('2024-03-31'),\n * { workingDays: [1,2,3,4,5], holidays: companyHolidays }\n * );\n */\nexport function countWorkingDays(\n startDate: Date,\n endDate: Date,\n options: {\n workingDays?: number[];\n holidays?: Date[];\n } = {}\n): WorkingDaysResult {\n const workDays = options.workingDays || DEFAULT_WORK_SCHEDULE.workingDays;\n const holidaySet = new Set(\n (options.holidays || []).map(d => new Date(d).toDateString())\n );\n\n let totalDays = 0;\n let workingDays = 0;\n let holidays = 0;\n let weekends = 0;\n\n const current = new Date(startDate);\n current.setHours(0, 0, 0, 0);\n const end = new Date(endDate);\n end.setHours(0, 0, 0, 0);\n\n while (current <= end) {\n totalDays++;\n const isHoliday = holidaySet.has(current.toDateString());\n const isWorkDay = workDays.includes(current.getDay());\n\n if (isHoliday) {\n holidays++;\n } else if (isWorkDay) {\n workingDays++;\n } else {\n weekends++;\n }\n\n current.setDate(current.getDate() + 1);\n }\n\n return { totalDays, workingDays, weekends, holidays };\n}\n\n/**\n * Calculate proration ratio for partial months\n *\n * @example\n * const proration = calculateProration(\n * employee.hireDate,\n * employee.terminationDate,\n * periodStart,\n * periodEnd\n * );\n */\nexport function calculateProration(\n hireDate: Date,\n terminationDate: Date | null | undefined,\n periodStart: Date,\n periodEnd: Date\n): ProrationResult {\n const hire = new Date(hireDate);\n hire.setHours(0, 0, 0, 0);\n const term = terminationDate ? new Date(terminationDate) : null;\n if (term) term.setHours(0, 0, 0, 0);\n const start = new Date(periodStart);\n start.setHours(0, 0, 0, 0);\n const end = new Date(periodEnd);\n end.setHours(0, 0, 0, 0);\n\n // Employee not active in this period\n if (hire > end || (term && term < start)) {\n return { ratio: 0, reason: 'full', isProrated: true };\n }\n\n // Effective dates within the period\n const effectiveStart = hire > start ? hire : start;\n const effectiveEnd = term && term < end ? term : end;\n\n // Calculate days\n const totalDays = Math.ceil((end.getTime() - start.getTime()) / 86400000) + 1;\n const actualDays = Math.ceil((effectiveEnd.getTime() - effectiveStart.getTime()) / 86400000) + 1;\n const ratio = Math.min(1, Math.max(0, actualDays / totalDays));\n\n // Determine reason\n const isNewHire = hire > start;\n const isTermination = term !== null && term < end;\n \n let reason: ProrationResult['reason'] = 'full';\n if (isNewHire && isTermination) {\n reason = 'both';\n } else if (isNewHire) {\n reason = 'new_hire';\n } else if (isTermination) {\n reason = 'termination';\n }\n\n return { ratio, reason, isProrated: ratio < 1 };\n}\n\n/**\n * Internal simple tax calculation\n * For multi-jurisdiction tax, use the jurisdiction system\n * @internal\n */\nfunction calculateSimpleTax(\n monthlyIncome: number,\n brackets: Array<{ min: number; max: number; rate: number }> = DEFAULT_TAX_BRACKETS\n): TaxResult {\n const annualIncome = monthlyIncome * 12;\n let annualTax = 0;\n\n for (const bracket of brackets) {\n if (annualIncome <= bracket.min) continue;\n const taxableInBracket = Math.min(annualIncome, bracket.max) - bracket.min;\n annualTax += taxableInBracket * bracket.rate;\n }\n\n const monthlyTax = Math.round(annualTax / 12);\n const effectiveRate = monthlyIncome > 0 ? monthlyTax / monthlyIncome : 0;\n\n return { amount: monthlyTax, effectiveRate };\n}\n\n/**\n * Calculate attendance deduction\n *\n * @example\n * const deduction = calculateAttendanceDeduction(22, 20, dailyRate);\n */\nexport function calculateAttendanceDeduction(\n expectedDays: number,\n actualDays: number,\n dailyRate: number,\n maxDeductionPercent = 100\n): number {\n const absentDays = Math.max(0, expectedDays - actualDays);\n const deduction = Math.round(absentDays * dailyRate);\n const maxDeduction = Math.round((dailyRate * expectedDays * maxDeductionPercent) / 100);\n return Math.min(deduction, maxDeduction);\n}\n\n/**\n * Calculate complete salary breakdown\n *\n * This is the main function for salary calculation.\n * Pass all data from YOUR app, get back complete breakdown.\n *\n * Note: Uses simple tax calculation. For multi-jurisdiction tax,\n * use the jurisdiction system instead.\n *\n * @example\n * const result = calculateSalaryBreakdown({\n * baseSalary: 100000,\n * hireDate: employee.hireDate,\n * terminationDate: employee.terminationDate,\n * periodStart: new Date('2024-03-01'),\n * periodEnd: new Date('2024-03-31'),\n * allowances: [{ type: 'housing', amount: 20000, taxable: true }],\n * deductions: [{ type: 'provident_fund', amount: 5000 }],\n * options: { holidays: companyHolidays },\n * attendance: { expectedDays: 22, actualDays: 20 },\n * });\n */\nexport function calculateSalaryBreakdown(params: {\n baseSalary: number;\n hireDate: Date;\n terminationDate?: Date | null;\n periodStart: Date;\n periodEnd: Date;\n allowances?: Array<{ type: string; amount: number; taxable?: boolean }>;\n deductions?: Array<{ type: string; amount: number }>;\n options?: PayrollProcessingOptions;\n attendance?: AttendanceInput;\n}): SalaryCalculationResult {\n const {\n baseSalary,\n hireDate,\n terminationDate,\n periodStart,\n periodEnd,\n allowances = [],\n deductions = [],\n options = {},\n attendance,\n } = params;\n\n // 1. Calculate working days\n const workSchedule = { ...DEFAULT_WORK_SCHEDULE, ...options.workSchedule };\n const workingDays = countWorkingDays(periodStart, periodEnd, {\n workingDays: workSchedule.workingDays,\n holidays: options.holidays,\n });\n\n // 2. Calculate proration\n const proration = options.skipProration\n ? { ratio: 1, reason: 'full' as const, isProrated: false }\n : calculateProration(hireDate, terminationDate, periodStart, periodEnd);\n\n // 3. Prorate base salary\n const proratedBase = Math.round(baseSalary * proration.ratio);\n\n // 4. Process allowances (prorate)\n const processedAllowances = allowances.map(a => ({\n type: a.type,\n amount: Math.round(a.amount * proration.ratio),\n taxable: a.taxable ?? true,\n }));\n const totalAllowances = processedAllowances.reduce((sum, a) => sum + a.amount, 0);\n\n // 5. Process deductions (prorate)\n const processedDeductions = deductions.map(d => ({\n type: d.type,\n amount: Math.round(d.amount * proration.ratio),\n }));\n\n // 6. Attendance deduction\n let attendanceDeduction = 0;\n if (attendance && !options.skipAttendance && workingDays.workingDays > 0) {\n const dailyRate = proratedBase / workingDays.workingDays;\n attendanceDeduction = calculateAttendanceDeduction(\n attendance.expectedDays,\n attendance.actualDays,\n dailyRate\n );\n if (attendanceDeduction > 0) {\n processedDeductions.push({ type: 'attendance', amount: attendanceDeduction });\n }\n }\n\n // 7. Calculate gross salary\n const grossSalary = proratedBase + totalAllowances;\n\n // 8. Calculate tax (simple calculation - for multi-jurisdiction, use jurisdiction system)\n let taxAmount = 0;\n if (!options.skipTax) {\n const taxableAllowances = processedAllowances\n .filter(a => a.taxable)\n .reduce((sum, a) => sum + a.amount, 0);\n const taxableIncome = proratedBase + taxableAllowances;\n const taxResult = calculateSimpleTax(taxableIncome);\n taxAmount = taxResult.amount;\n if (taxAmount > 0) {\n processedDeductions.push({ type: 'tax', amount: taxAmount });\n }\n }\n\n // 9. Calculate net salary\n const totalDeductions = processedDeductions\n .filter(d => d.type !== 'tax') // Exclude only tax, include attendance\n .reduce((sum, d) => sum + d.amount, 0);\n const netSalary = grossSalary - totalDeductions - taxAmount;\n\n return {\n baseSalary,\n proratedBase,\n totalAllowances,\n totalDeductions,\n attendanceDeduction,\n grossSalary,\n taxAmount,\n netSalary,\n proration,\n workingDays,\n breakdown: {\n allowances: processedAllowances,\n deductions: processedDeductions,\n },\n };\n}\n\n/**\n * Get pay period dates for a given month\n *\n * @example\n * const period = getPayPeriod(3, 2024); // March 2024\n */\nexport function getPayPeriod(\n month: number,\n year: number,\n payDay = 28\n): { startDate: Date; endDate: Date; payDate: Date } {\n const startDate = new Date(year, month - 1, 1);\n const endDate = new Date(year, month, 0); // Last day of month\n const payDate = new Date(year, month - 1, Math.min(payDay, endDate.getDate()));\n return { startDate, endDate, payDate };\n}\n\n","/**\n * @classytic/payroll - Pro-Rating Calculator\n *\n * Pure functions for salary pro-rating calculations.\n * No database dependencies - can be used client-side!\n *\n * Handles:\n * - Mid-period hires\n * - Mid-period terminations\n * - Working days (not calendar days)\n * - Holidays exclusion\n *\n * @packageDocumentation\n */\n\nimport { countWorkingDays } from '../core/config.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Input for pro-rating calculation\n */\nexport interface ProRatingInput {\n /**\n * Employee hire date\n */\n hireDate: Date;\n\n /**\n * Employee termination date (null if still employed)\n */\n terminationDate: Date | null;\n\n /**\n * Start of the salary period\n */\n periodStart: Date;\n\n /**\n * End of the salary period\n */\n periodEnd: Date;\n\n /**\n * Working days of the week (1=Monday, 7=Sunday)\n * @default [1, 2, 3, 4, 5] (Monday-Friday)\n */\n workingDays: number[];\n\n /**\n * Public holidays to exclude from working days\n * @default []\n */\n holidays?: Date[];\n}\n\n/**\n * Result of pro-rating calculation\n */\nexport interface ProRatingResult {\n /**\n * Whether the salary needs to be pro-rated\n */\n isProRated: boolean;\n\n /**\n * Pro-rating ratio (0-1)\n * 1 = full salary, 0.5 = half salary, etc.\n */\n ratio: number;\n\n /**\n * Total working days in the period\n */\n periodWorkingDays: number;\n\n /**\n * Working days the employee was actually employed\n */\n effectiveWorkingDays: number;\n\n /**\n * Effective start date (max of hire date and period start)\n */\n effectiveStart: Date;\n\n /**\n * Effective end date (min of termination date and period end)\n */\n effectiveEnd: Date;\n}\n\n// ============================================================================\n// Pure Functions\n// ============================================================================\n\n/**\n * Calculate pro-rating for mid-period hires/terminations\n *\n * This function uses WORKING DAYS (not calendar days) for accurate pro-rating.\n *\n * @example\n * ```typescript\n * // Employee hired on March 15th, process March salary\n * const result = calculateProRating({\n * hireDate: new Date('2024-03-15'),\n * terminationDate: null,\n * periodStart: new Date('2024-03-01'),\n * periodEnd: new Date('2024-03-31'),\n * workingDays: [1, 2, 3, 4, 5], // Mon-Fri\n * });\n * \n * console.log(result);\n * // {\n * // isProRated: true,\n * // ratio: 0.64, // Worked 14 out of 22 working days\n * // periodWorkingDays: 22,\n * // effectiveWorkingDays: 14\n * // }\n * ```\n *\n * @param input - Pro-rating calculation parameters\n * @returns Pro-rating result with ratio and working days breakdown\n *\n * @pure This function has no side effects and doesn't access external state\n */\nexport function calculateProRating(input: ProRatingInput): ProRatingResult {\n const { hireDate, terminationDate, periodStart, periodEnd, workingDays, holidays = [] } = input;\n\n const hire = new Date(hireDate);\n const termination = terminationDate ? new Date(terminationDate) : null;\n\n // Determine the actual start and end dates for this employee in this period\n const effectiveStart = hire > periodStart ? hire : periodStart;\n const effectiveEnd = termination && termination < periodEnd ? termination : periodEnd;\n\n // If employee wasn't active during this period at all\n if (effectiveStart > periodEnd || (termination && termination < periodStart)) {\n const periodWorkingDays = countWorkingDays(periodStart, periodEnd, { workingDays, holidays }).workingDays;\n return {\n isProRated: true,\n ratio: 0,\n periodWorkingDays,\n effectiveWorkingDays: 0,\n effectiveStart: periodStart,\n effectiveEnd: periodStart, // Effectively zero days\n };\n }\n\n // Calculate working days for the full period\n const periodWorkingDays = countWorkingDays(periodStart, periodEnd, { workingDays, holidays }).workingDays;\n\n // Calculate working days the employee was actually employed\n const effectiveWorkingDays = countWorkingDays(effectiveStart, effectiveEnd, { workingDays, holidays }).workingDays;\n\n // Calculate ratio\n const ratio = periodWorkingDays > 0 \n ? Math.min(1, Math.max(0, effectiveWorkingDays / periodWorkingDays)) \n : 0;\n\n // Is pro-rated if ratio is less than 1\n const isProRated = ratio < 1;\n\n return {\n isProRated,\n ratio,\n periodWorkingDays,\n effectiveWorkingDays,\n effectiveStart,\n effectiveEnd,\n };\n}\n\n/**\n * Calculate pro-rated amount from base amount and ratio\n *\n * @example\n * ```typescript\n * const proRatedSalary = applyProRating(100000, 0.64); // 64000\n * ```\n *\n * @param baseAmount - Original amount\n * @param ratio - Pro-rating ratio (0-1)\n * @returns Pro-rated amount (rounded)\n *\n * @pure No side effects\n */\nexport function applyProRating(baseAmount: number, ratio: number): number {\n return Math.round(baseAmount * ratio);\n}\n\n/**\n * Check if pro-rating should be applied for a given hire/termination scenario\n *\n * @param hireDate - Employee hire date\n * @param terminationDate - Employee termination date (null if active)\n * @param periodStart - Salary period start\n * @param periodEnd - Salary period end\n * @returns True if pro-rating is needed\n *\n * @pure No side effects\n */\nexport function shouldProRate(\n hireDate: Date,\n terminationDate: Date | null,\n periodStart: Date,\n periodEnd: Date\n): boolean {\n const hire = new Date(hireDate);\n const termination = terminationDate ? new Date(terminationDate) : null;\n\n // Pro-rate if hired after period start\n if (hire > periodStart) return true;\n\n // Pro-rate if terminated before period end\n if (termination && termination < periodEnd) return true;\n\n return false;\n}\n\n","/**\n * @classytic/payroll - Attendance Deduction Calculator\n *\n * Pure functions for calculating salary deductions based on attendance.\n * No database dependencies - can be used client-side!\n *\n * @packageDocumentation\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Input for attendance deduction calculation\n */\nexport interface AttendanceDeductionInput {\n /**\n * Expected working days in the period (for this specific employee)\n * Should account for hire/termination dates\n */\n expectedWorkingDays: number;\n\n /**\n * Actual working days the employee was present\n */\n actualWorkingDays: number;\n\n /**\n * Daily salary rate for this employee\n * Calculated as: baseAmount / expectedWorkingDays\n */\n dailyRate: number;\n}\n\n/**\n * Result of attendance deduction calculation\n */\nexport interface AttendanceDeductionResult {\n /**\n * Number of absent days\n */\n absentDays: number;\n\n /**\n * Total deduction amount\n */\n deductionAmount: number;\n\n /**\n * Daily rate used for calculation\n */\n dailyRate: number;\n\n /**\n * Whether any deduction was applied\n */\n hasDeduction: boolean;\n}\n\n// ============================================================================\n// Pure Functions\n// ============================================================================\n\n/**\n * Calculate attendance deduction based on absent days\n *\n * @example\n * ```typescript\n * const result = calculateAttendanceDeduction({\n * expectedWorkingDays: 22,\n * actualWorkingDays: 20, // 2 days absent\n * dailyRate: 4545, // 100000 / 22\n * });\n *\n * console.log(result);\n * // {\n * // absentDays: 2,\n * // deductionAmount: 9090,\n * // dailyRate: 4545,\n * // hasDeduction: true\n * // }\n * ```\n *\n * @param input - Attendance deduction parameters\n * @returns Deduction result with breakdown\n *\n * @pure This function has no side effects\n */\nexport function calculateAttendanceDeduction(input: AttendanceDeductionInput): AttendanceDeductionResult {\n const { expectedWorkingDays, actualWorkingDays, dailyRate } = input;\n\n // Guard against negative values\n const expected = Math.max(0, expectedWorkingDays);\n const actual = Math.max(0, actualWorkingDays);\n const rate = Math.max(0, dailyRate);\n\n // Calculate absent days (cannot be negative)\n const absentDays = Math.max(0, expected - actual);\n\n // Calculate deduction amount\n const deductionAmount = Math.round(absentDays * rate);\n\n return {\n absentDays,\n deductionAmount,\n dailyRate: rate,\n hasDeduction: deductionAmount > 0,\n };\n}\n\n/**\n * Calculate daily rate from monthly salary and working days\n *\n * @example\n * ```typescript\n * const daily = calculateDailyRate(100000, 22); // 4545\n * ```\n *\n * @param monthlySalary - Monthly base salary\n * @param workingDays - Working days in the month\n * @returns Daily rate (rounded)\n *\n * @pure No side effects\n */\nexport function calculateDailyRate(monthlySalary: number, workingDays: number): number {\n if (workingDays <= 0) return 0;\n return Math.round(monthlySalary / workingDays);\n}\n\n/**\n * Calculate hourly rate from monthly salary\n *\n * @example\n * ```typescript\n * const hourly = calculateHourlyRate(100000, 22, 8); // 568\n * ```\n *\n * @param monthlySalary - Monthly base salary\n * @param workingDays - Working days in the month\n * @param hoursPerDay - Hours per working day (default: 8)\n * @returns Hourly rate (rounded)\n *\n * @pure No side effects\n */\nexport function calculateHourlyRate(\n monthlySalary: number,\n workingDays: number,\n hoursPerDay: number = 8\n): number {\n const dailyRate = calculateDailyRate(monthlySalary, workingDays);\n if (hoursPerDay <= 0) return 0;\n return Math.round(dailyRate / hoursPerDay);\n}\n\n/**\n * Calculate deduction for partial day absence (half-day, quarter-day, etc.)\n *\n * @example\n * ```typescript\n * // Half-day absence\n * const deduction = calculatePartialDayDeduction(4545, 0.5); // 2272\n * ```\n *\n * @param dailyRate - Daily salary rate\n * @param fractionAbsent - Fraction of day absent (0-1)\n * @returns Deduction amount (rounded)\n *\n * @pure No side effects\n */\nexport function calculatePartialDayDeduction(dailyRate: number, fractionAbsent: number): number {\n const fraction = Math.min(1, Math.max(0, fractionAbsent));\n return Math.round(dailyRate * fraction);\n}\n\n/**\n * Calculate total attendance deduction including full and partial day absences\n *\n * @example\n * ```typescript\n * const result = calculateTotalAttendanceDeduction({\n * dailyRate: 4545,\n * fullDayAbsences: 2,\n * partialDayAbsences: [0.5, 0.25], // Half-day + quarter-day\n * });\n * \n * console.log(result);\n * // {\n * // fullDayDeduction: 9090,\n * // partialDayDeduction: 3408,\n * // totalDeduction: 12498\n * // }\n * ```\n *\n * @param input - Absence breakdown\n * @returns Deduction breakdown and total\n *\n * @pure No side effects\n */\nexport function calculateTotalAttendanceDeduction(input: {\n dailyRate: number;\n fullDayAbsences?: number;\n partialDayAbsences?: number[];\n}): {\n fullDayDeduction: number;\n partialDayDeduction: number;\n totalDeduction: number;\n} {\n const { dailyRate, fullDayAbsences = 0, partialDayAbsences = [] } = input;\n\n // Full day deductions\n const fullDayDeduction = Math.round(dailyRate * Math.max(0, fullDayAbsences));\n\n // Partial day deductions\n const partialDayDeduction = partialDayAbsences.reduce(\n (sum, fraction) => sum + calculatePartialDayDeduction(dailyRate, fraction),\n 0\n );\n\n return {\n fullDayDeduction,\n partialDayDeduction,\n totalDeduction: fullDayDeduction + partialDayDeduction,\n };\n}\n\n","/**\n * @classytic/payroll - Salary Calculator\n *\n * Pure functions for complete salary breakdown calculations.\n * No database dependencies - can be used client-side!\n *\n * This is the SINGLE SOURCE OF TRUTH for all salary calculations.\n *\n * @packageDocumentation\n */\n\nimport type {\n Compensation,\n PayrollBreakdown,\n Allowance,\n Deduction,\n TaxBracket,\n} from '../types.js';\nimport { calculateGross, calculateNet, sumAllowances, sumDeductions, applyTaxBrackets } from '../utils/calculation.js';\nimport { countWorkingDays } from '../core/config.js';\nimport { calculateProRating, type ProRatingInput, type ProRatingResult } from './prorating.calculator.js';\nimport { calculateAttendanceDeduction, calculateDailyRate, type AttendanceDeductionInput } from './attendance.calculator.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Input for salary breakdown calculation\n */\nexport interface SalaryCalculationInput {\n /**\n * Employee data (minimal subset needed for calculation)\n */\n employee: {\n hireDate: Date;\n terminationDate?: Date | null;\n compensation: Compensation;\n workSchedule?: {\n workingDays?: number[];\n hoursPerDay?: number;\n };\n };\n\n /**\n * Salary period\n */\n period: {\n month: number;\n year: number;\n startDate: Date;\n endDate: Date;\n };\n\n /**\n * Attendance data (optional)\n */\n attendance?: {\n expectedDays?: number;\n actualDays?: number;\n } | null;\n\n /**\n * Processing options\n */\n options?: {\n holidays?: Date[];\n workSchedule?: {\n workingDays?: number[];\n hoursPerDay?: number;\n };\n skipTax?: boolean;\n skipAttendance?: boolean;\n skipProration?: boolean;\n };\n\n /**\n * Configuration (minimal subset)\n */\n config: {\n allowProRating: boolean;\n autoDeductions: boolean;\n defaultCurrency: string;\n attendanceIntegration: boolean;\n };\n\n /**\n * Tax brackets for the employee's currency\n */\n taxBrackets: TaxBracket[];\n}\n\n/**\n * Processed allowance with calculated amount\n */\nexport interface ProcessedAllowance {\n type: string;\n amount: number;\n taxable: boolean;\n originalAmount?: number; // Before pro-rating\n isPercentage?: boolean;\n value?: number;\n}\n\n/**\n * Processed deduction with calculated amount\n */\nexport interface ProcessedDeduction {\n type: string;\n amount: number;\n description?: string;\n originalAmount?: number; // Before pro-rating\n isPercentage?: boolean;\n value?: number;\n}\n\n// ============================================================================\n// Pure Functions\n// ============================================================================\n\n/**\n * Calculate complete salary breakdown\n *\n * This is the SINGLE SOURCE OF TRUTH for salary calculations.\n * All payroll processing uses this function.\n *\n * @example\n * ```typescript\n * const breakdown = calculateSalaryBreakdown({\n * employee: {\n * hireDate: new Date('2024-01-01'),\n * compensation: {\n * baseAmount: 100000,\n * currency: 'USD',\n * allowances: [{ type: 'housing', amount: 20000, taxable: true }],\n * deductions: [{ type: 'insurance', amount: 5000 }],\n * },\n * },\n * period: {\n * month: 3,\n * year: 2024,\n * startDate: new Date('2024-03-01'),\n * endDate: new Date('2024-03-31'),\n * },\n * attendance: {\n * expectedDays: 22,\n * actualDays: 20, // 2 days absent\n * },\n * options: {\n * holidays: [new Date('2024-03-26')],\n * },\n * config: {\n * allowProRating: true,\n * autoDeductions: true,\n * defaultCurrency: 'USD',\n * attendanceIntegration: true,\n * },\n * taxBrackets: [...],\n * });\n * ```\n *\n * @param input - Salary calculation parameters\n * @returns Complete payroll breakdown\n *\n * @pure This function has no side effects and doesn't access database\n */\nexport function calculateSalaryBreakdown(input: SalaryCalculationInput): PayrollBreakdown {\n const { employee, period, attendance, options = {}, config, taxBrackets } = input;\n\n const comp = employee.compensation;\n const originalBaseAmount = comp.baseAmount;\n\n // 1. Calculate pro-rating (if applicable)\n const proRating = calculateProRatingForSalary(\n employee.hireDate,\n employee.terminationDate || null,\n period.startDate,\n period.endDate,\n options,\n employee.workSchedule\n );\n\n // 2. Apply pro-rating to base salary\n let baseAmount = originalBaseAmount;\n if (proRating.isProRated && config.allowProRating && !options.skipProration) {\n baseAmount = Math.round(baseAmount * proRating.ratio);\n }\n\n // 3. Filter allowances by effective date\n const effectiveAllowances = (comp.allowances || [])\n .filter((a) => isEffectiveForPeriod(a, period.startDate, period.endDate));\n\n // 4. Filter deductions by effective date\n const effectiveDeductions = (comp.deductions || [])\n .filter((d) => isEffectiveForPeriod(d, period.startDate, period.endDate))\n .filter((d) => d.auto || d.recurring);\n\n // 5. Calculate allowances (handle percentages and pro-rating)\n const allowances = processAllowances(effectiveAllowances, originalBaseAmount, proRating, config);\n\n // 6. Calculate deductions (handle percentages and pro-rating)\n const deductions = processDeductions(effectiveDeductions, originalBaseAmount, proRating, config);\n\n // 7. Calculate attendance deduction\n if (!options.skipAttendance && config.attendanceIntegration && attendance) {\n const attendanceDeductionResult = calculateAttendanceDeductionFromData(\n attendance,\n baseAmount,\n proRating.effectiveWorkingDays\n );\n\n if (attendanceDeductionResult.hasDeduction) {\n deductions.push({\n type: 'absence',\n amount: attendanceDeductionResult.deductionAmount,\n description: `Unpaid leave deduction (${attendanceDeductionResult.absentDays} days)`,\n });\n }\n }\n\n // 8. Calculate gross salary\n const grossSalary = calculateGross(baseAmount, allowances);\n\n // 9. Calculate taxable amount (only taxable allowances)\n const taxableAllowances = allowances.filter((a) => a.taxable);\n const taxableAmount = baseAmount + sumAllowances(taxableAllowances);\n\n // 10. Calculate tax\n let taxAmount = 0;\n if (!options.skipTax && taxBrackets.length > 0 && config.autoDeductions) {\n // Annualize the taxable amount for tax bracket calculation\n const annualTaxable = taxableAmount * 12;\n const annualTax = applyTaxBrackets(annualTaxable, taxBrackets);\n taxAmount = Math.round(annualTax / 12); // Monthly tax\n }\n\n // Add tax to deductions if applicable\n if (taxAmount > 0) {\n deductions.push({\n type: 'tax',\n amount: taxAmount,\n description: 'Income tax',\n });\n }\n\n // 11. Calculate net salary\n const netSalary = calculateNet(grossSalary, deductions);\n\n // 12. Build final breakdown\n return {\n baseAmount,\n allowances,\n deductions,\n grossSalary,\n netSalary,\n taxableAmount,\n taxAmount,\n workingDays: proRating.periodWorkingDays,\n actualDays: proRating.effectiveWorkingDays,\n proRatedAmount: (proRating.isProRated && !options.skipProration) ? baseAmount : 0,\n attendanceDeduction: attendance\n ? deductions.find((d) => d.type === 'absence')?.amount || 0\n : 0,\n };\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Check if allowance/deduction is effective for a given period\n */\nfunction isEffectiveForPeriod(\n item: { effectiveFrom?: Date | null; effectiveTo?: Date | null },\n periodStart: Date,\n periodEnd: Date\n): boolean {\n const effectiveFrom = item.effectiveFrom ? new Date(item.effectiveFrom) : new Date(0);\n const effectiveTo = item.effectiveTo ? new Date(item.effectiveTo) : new Date('2099-12-31');\n\n // Item is effective if its range overlaps with the period\n return effectiveFrom <= periodEnd && effectiveTo >= periodStart;\n}\n\n/**\n * Calculate pro-rating for salary calculation\n */\nfunction calculateProRatingForSalary(\n hireDate: Date,\n terminationDate: Date | null,\n periodStart: Date,\n periodEnd: Date,\n options: SalaryCalculationInput['options'],\n employeeWorkSchedule?: { workingDays?: number[] }\n): ProRatingResult {\n // Work schedule: prefer operation override, then employee schedule, then Mon-Fri default\n const workingDays =\n options?.workSchedule?.workingDays ||\n employeeWorkSchedule?.workingDays ||\n [1, 2, 3, 4, 5];\n\n const holidays = options?.holidays || [];\n\n return calculateProRating({\n hireDate,\n terminationDate,\n periodStart,\n periodEnd,\n workingDays,\n holidays,\n });\n}\n\n/**\n * Process allowances (handle percentages and pro-rating)\n */\nfunction processAllowances(\n allowances: Allowance[],\n originalBaseAmount: number,\n proRating: ProRatingResult,\n config: SalaryCalculationInput['config']\n): ProcessedAllowance[] {\n return allowances.map((a) => {\n // Calculate from original base (percentage) or use fixed amount\n let amount = a.isPercentage && a.value !== undefined\n ? Math.round((originalBaseAmount * a.value) / 100)\n : a.amount;\n\n const originalAmount = amount;\n\n // Apply pro-rating ONCE if needed\n if (proRating.isProRated && config.allowProRating) {\n amount = Math.round(amount * proRating.ratio);\n }\n\n return {\n type: a.type,\n amount,\n taxable: a.taxable ?? true,\n originalAmount,\n isPercentage: a.isPercentage,\n value: a.value,\n };\n });\n}\n\n/**\n * Process deductions (handle percentages and pro-rating)\n */\nfunction processDeductions(\n deductions: Deduction[],\n originalBaseAmount: number,\n proRating: ProRatingResult,\n config: SalaryCalculationInput['config']\n): ProcessedDeduction[] {\n return deductions.map((d) => {\n // Calculate from original base (percentage) or use fixed amount\n let amount = d.isPercentage && d.value !== undefined\n ? Math.round((originalBaseAmount * d.value) / 100)\n : d.amount;\n\n const originalAmount = amount;\n\n // Apply pro-rating ONCE if needed\n if (proRating.isProRated && config.allowProRating) {\n amount = Math.round(amount * proRating.ratio);\n }\n\n return {\n type: d.type,\n amount,\n description: d.description,\n originalAmount,\n isPercentage: d.isPercentage,\n value: d.value,\n };\n });\n}\n\n/**\n * Calculate attendance deduction from attendance data\n */\nfunction calculateAttendanceDeductionFromData(\n attendance: { expectedDays?: number; actualDays?: number },\n baseAmount: number,\n effectiveWorkingDays: number\n): {\n hasDeduction: boolean;\n deductionAmount: number;\n absentDays: number;\n} {\n const expectedDays = attendance.expectedDays ?? effectiveWorkingDays;\n const actualDays = attendance.actualDays;\n\n if (actualDays === undefined) {\n return { hasDeduction: false, deductionAmount: 0, absentDays: 0 };\n }\n\n // Daily rate based on expected working days for THIS employee in THIS period\n const dailyRate = calculateDailyRate(baseAmount, expectedDays);\n\n const result = calculateAttendanceDeduction({\n expectedWorkingDays: expectedDays,\n actualWorkingDays: actualDays,\n dailyRate,\n });\n\n return {\n hasDeduction: result.hasDeduction,\n deductionAmount: result.deductionAmount,\n absentDays: result.absentDays,\n };\n}\n\n"]}
@@ -0,0 +1,314 @@
1
+ import { E as EmployeeDocument, P as PayrollRecordDocument, A as AnyDocument, y as LeaveRequestDocument, v as TaxWithholdingDocument, z as HRMConfig, S as SingleTenantConfig, C as Logger } from '../types-BN3K_Uhr.js';
2
+ export { aw as AttendanceInput, ae as CompensationChangedEventPayload, az as DEFAULT_TAX_BRACKETS, ay as DEFAULT_WORK_SCHEDULE, a6 as EmployeeHiredEventPayload, a8 as EmployeeRehiredEventPayload, a7 as EmployeeTerminatedEventPayload, Z as EventBus, af as MilestoneAchievedEventPayload, aq as NotificationPluginOptions, ac as PayrollCompletedEventPayload, a5 as PayrollEventHandler, d as PayrollEventMap, e as PayrollEventType, ad as PayrollExportedEventPayload, c as PayrollPluginDefinition, as as PayrollProcessingOptions, an as PluginContext, ap as PluginHooks, ao as PluginLogger, ah as PluginManager, au as ProrationResult, ax as SalaryCalculationResult, ab as SalaryFailedEventPayload, aa as SalaryProcessedEventPayload, a9 as SalaryUpdatedEventPayload, av as TaxResult, W as WebhookConfig, f as WebhookDelivery, ag as WebhookManager, ar as WorkSchedule, at as WorkingDaysResult, aC as calculateAttendanceDeduction, aB as calculateProration, aD as calculateSalaryBreakdown, aA as countWorkingDays, _ as createEventBus, am as createNotificationPlugin, ai as definePlugin, $ as getEventBus, aE as getPayPeriod, aj as loggingPlugin, ak as metricsPlugin, al as notificationPlugin, a1 as onEmployeeHired, a4 as onMilestoneAchieved, a3 as onPayrollCompleted, a2 as onSalaryProcessed, a0 as resetEventBus } from '../types-BN3K_Uhr.js';
3
+ export { I as IdempotencyManager, a as IdempotentResult, g as generatePayrollIdempotencyKey } from '../idempotency-Cw2CWicb.js';
4
+ import { Model, ClientSession } from 'mongoose';
5
+
6
+ /**
7
+ * @classytic/payroll - Result Type
8
+ *
9
+ * Rust-inspired Result type for type-safe error handling
10
+ * No more try/catch everywhere - explicit error handling
11
+ */
12
+ /** Success result */
13
+ interface Ok<T> {
14
+ readonly ok: true;
15
+ readonly value: T;
16
+ }
17
+ /** Error result */
18
+ interface Err<E> {
19
+ readonly ok: false;
20
+ readonly error: E;
21
+ }
22
+ /**
23
+ * Create a success result
24
+ */
25
+ declare function ok<T>(value: T): Ok<T>;
26
+ /**
27
+ * Create an error result
28
+ */
29
+ declare function err<E>(error: E): Err<E>;
30
+ /**
31
+ * Check if result is success
32
+ */
33
+ declare function isOk<T, E>(result: Result<T, E>): result is Ok<T>;
34
+ /**
35
+ * Check if result is error
36
+ */
37
+ declare function isErr<T, E>(result: Result<T, E>): result is Err<E>;
38
+ /**
39
+ * Unwrap result value or throw error
40
+ */
41
+ declare function unwrap<T, E>(result: Result<T, E>): T;
42
+ /**
43
+ * Unwrap result value or return default
44
+ */
45
+ declare function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T;
46
+ /**
47
+ * Unwrap result value or compute default
48
+ */
49
+ declare function unwrapOrElse<T, E>(result: Result<T, E>, fn: (error: E) => T): T;
50
+ /**
51
+ * Map success value
52
+ */
53
+ declare function map<T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;
54
+ /**
55
+ * Map error value
56
+ */
57
+ declare function mapErr<T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;
58
+ /**
59
+ * FlatMap (chain) success value
60
+ */
61
+ declare function flatMap<T, U, E>(result: Result<T, E>, fn: (value: T) => Result<U, E>): Result<U, E>;
62
+ /**
63
+ * Try/catch wrapper for async functions
64
+ */
65
+ declare function tryCatch<T, E = Error>(fn: () => Promise<T>, errorTransform?: (error: unknown) => E): Promise<Result<T, E>>;
66
+ /**
67
+ * Try/catch wrapper for sync functions
68
+ */
69
+ declare function tryCatchSync<T, E = Error>(fn: () => T, errorTransform?: (error: unknown) => E): Result<T, E>;
70
+ /**
71
+ * Combine multiple results into one
72
+ */
73
+ declare function all<T, E>(results: Result<T, E>[]): Result<T[], E>;
74
+ /**
75
+ * Pattern match on result
76
+ */
77
+ declare function match<T, E, R>(result: Result<T, E>, handlers: {
78
+ ok: (value: T) => R;
79
+ err: (error: E) => R;
80
+ }): R;
81
+ /**
82
+ * Convert Promise<Result> to Result<Promise>
83
+ */
84
+ declare function fromPromise<T, E = Error>(promise: Promise<T>, errorTransform?: (error: unknown) => E): Promise<Result<T, E>>;
85
+ /**
86
+ * Create Result from nullable value
87
+ */
88
+ declare function fromNullable<T, E>(value: T | null | undefined, error: E): Result<T, E>;
89
+ declare class ResultClass<T, E = Error> {
90
+ private readonly result;
91
+ private constructor();
92
+ static ok<T>(value: T): ResultClass<T, never>;
93
+ static err<E>(error: E): ResultClass<never, E>;
94
+ static fromAsync<T, E = Error>(fn: () => Promise<T>, errorTransform?: (error: unknown) => E): Promise<ResultClass<T, E>>;
95
+ isOk(): boolean;
96
+ isErr(): boolean;
97
+ unwrap(): T;
98
+ unwrapOr(defaultValue: T): T;
99
+ map<U>(fn: (value: T) => U): ResultClass<U, E>;
100
+ mapErr<F>(fn: (error: E) => F): ResultClass<T, F>;
101
+ flatMap<U>(fn: (value: T) => Result<U, E>): ResultClass<U, E>;
102
+ match<R>(handlers: {
103
+ ok: (value: T) => R;
104
+ err: (error: E) => R;
105
+ }): R;
106
+ toResult(): Result<T, E>;
107
+ }
108
+ /** Result type - either success or error */
109
+ type Result<T, E = Error> = Ok<T> | Err<E>;
110
+ declare const Result: {
111
+ ok: typeof ok;
112
+ err: typeof err;
113
+ isOk: typeof isOk;
114
+ isErr: typeof isErr;
115
+ unwrap: typeof unwrap;
116
+ unwrapOr: typeof unwrapOr;
117
+ unwrapOrElse: typeof unwrapOrElse;
118
+ map: typeof map;
119
+ mapErr: typeof mapErr;
120
+ flatMap: typeof flatMap;
121
+ tryCatch: typeof tryCatch;
122
+ tryCatchSync: typeof tryCatchSync;
123
+ all: typeof all;
124
+ match: typeof match;
125
+ fromPromise: typeof fromPromise;
126
+ fromNullable: typeof fromNullable;
127
+ };
128
+
129
+ /**
130
+ * @classytic/payroll - Dependency Container
131
+ *
132
+ * Per-instance dependency injection container for service management.
133
+ * Enables clean dependency injection and testing without global state.
134
+ *
135
+ * IMPORTANT: This container is instance-based (not a singleton) to support:
136
+ * - Serverless/Lambda environments
137
+ * - Multi-app runtimes
138
+ * - Parallel testing
139
+ * - Multiple Payroll instances in the same process
140
+ */
141
+
142
+ /**
143
+ * Strongly-typed models container
144
+ * Uses specific document types instead of Model<any> for better DX
145
+ */
146
+ interface ModelsContainer<TEmployee extends EmployeeDocument = EmployeeDocument, TPayrollRecord extends PayrollRecordDocument = PayrollRecordDocument, TTransaction extends AnyDocument = AnyDocument, TAttendance extends AnyDocument = AnyDocument, TLeaveRequest extends LeaveRequestDocument = LeaveRequestDocument, TTaxWithholding extends TaxWithholdingDocument = TaxWithholdingDocument> {
147
+ EmployeeModel: Model<TEmployee>;
148
+ PayrollRecordModel: Model<TPayrollRecord>;
149
+ TransactionModel: Model<TTransaction>;
150
+ AttendanceModel?: Model<TAttendance> | null;
151
+ LeaveRequestModel?: Model<TLeaveRequest> | null;
152
+ TaxWithholdingModel?: Model<TTaxWithholding> | null;
153
+ }
154
+ /**
155
+ * Container configuration with generic model types
156
+ */
157
+ interface ContainerConfig<TEmployee extends EmployeeDocument = EmployeeDocument, TPayrollRecord extends PayrollRecordDocument = PayrollRecordDocument, TTransaction extends AnyDocument = AnyDocument, TAttendance extends AnyDocument = AnyDocument, TLeaveRequest extends LeaveRequestDocument = LeaveRequestDocument, TTaxWithholding extends TaxWithholdingDocument = TaxWithholdingDocument> {
158
+ models: ModelsContainer<TEmployee, TPayrollRecord, TTransaction, TAttendance, TLeaveRequest, TTaxWithholding>;
159
+ config?: Partial<HRMConfig>;
160
+ singleTenant?: SingleTenantConfig | null;
161
+ logger?: Logger;
162
+ }
163
+ /**
164
+ * Per-instance DI Container for Payroll
165
+ *
166
+ * Each Payroll instance creates its own Container, avoiding global state issues
167
+ * in serverless and multi-app environments.
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * // Each Payroll instance has its own container
172
+ * const payroll1 = createPayrollInstance()
173
+ * .withModels({ EmployeeModel, PayrollRecordModel, TransactionModel })
174
+ * .build();
175
+ *
176
+ * const payroll2 = createPayrollInstance()
177
+ * .withModels({ OtherEmployeeModel, OtherPayrollModel, OtherTransactionModel })
178
+ * .build();
179
+ *
180
+ * // They don't share state - perfect for multi-tenant or testing
181
+ * ```
182
+ */
183
+ declare class Container<TEmployee extends EmployeeDocument = EmployeeDocument, TPayrollRecord extends PayrollRecordDocument = PayrollRecordDocument, TTransaction extends AnyDocument = AnyDocument, TAttendance extends AnyDocument = AnyDocument, TLeaveRequest extends LeaveRequestDocument = LeaveRequestDocument, TTaxWithholding extends TaxWithholdingDocument = TaxWithholdingDocument> {
184
+ private _models;
185
+ private _config;
186
+ private _singleTenant;
187
+ private _logger;
188
+ private _initialized;
189
+ constructor();
190
+ /**
191
+ * Initialize container with configuration
192
+ */
193
+ initialize(config: ContainerConfig<TEmployee, TPayrollRecord, TTransaction, TAttendance, TLeaveRequest, TTaxWithholding>): void;
194
+ /**
195
+ * Check if container is initialized
196
+ */
197
+ isInitialized(): boolean;
198
+ /**
199
+ * Reset container (useful for testing)
200
+ */
201
+ reset(): void;
202
+ /**
203
+ * Ensure container is initialized
204
+ */
205
+ private ensureInitialized;
206
+ /**
207
+ * Get models container (strongly typed)
208
+ */
209
+ getModels(): ModelsContainer<TEmployee, TPayrollRecord, TTransaction, TAttendance, TLeaveRequest, TTaxWithholding>;
210
+ /**
211
+ * Get Employee model (strongly typed)
212
+ */
213
+ getEmployeeModel(): Model<TEmployee>;
214
+ /**
215
+ * Get PayrollRecord model (strongly typed)
216
+ */
217
+ getPayrollRecordModel(): Model<TPayrollRecord>;
218
+ /**
219
+ * Get Transaction model (strongly typed)
220
+ */
221
+ getTransactionModel(): Model<TTransaction>;
222
+ /**
223
+ * Get Attendance model (optional, strongly typed)
224
+ */
225
+ getAttendanceModel(): Model<TAttendance> | null;
226
+ /**
227
+ * Get LeaveRequest model (optional, strongly typed)
228
+ */
229
+ getLeaveRequestModel(): Model<TLeaveRequest> | null;
230
+ /**
231
+ * Get TaxWithholding model (optional, strongly typed)
232
+ */
233
+ getTaxWithholdingModel(): Model<TTaxWithholding> | null;
234
+ /**
235
+ * Get configuration
236
+ */
237
+ getConfig(): HRMConfig;
238
+ /**
239
+ * Get specific config section
240
+ */
241
+ getConfigSection<K extends keyof HRMConfig>(section: K): HRMConfig[K];
242
+ /**
243
+ * Check if single-tenant mode
244
+ */
245
+ isSingleTenant(): boolean;
246
+ /**
247
+ * Get single-tenant config
248
+ */
249
+ getSingleTenantConfig(): SingleTenantConfig | null;
250
+ /**
251
+ * Get organization ID (for single-tenant mode)
252
+ */
253
+ getOrganizationId(): string | null;
254
+ /**
255
+ * Get logger
256
+ */
257
+ getLogger(): Logger;
258
+ /**
259
+ * Set logger
260
+ */
261
+ setLogger(logger: Logger): void;
262
+ /**
263
+ * Has attendance integration
264
+ */
265
+ hasAttendanceIntegration(): boolean;
266
+ /**
267
+ * Create operation context with defaults
268
+ */
269
+ createOperationContext(overrides?: Partial<{
270
+ userId: string;
271
+ userName: string;
272
+ userRole: string;
273
+ organizationId: string;
274
+ session: ClientSession;
275
+ }>): {
276
+ userId?: string;
277
+ userName?: string;
278
+ userRole?: string;
279
+ organizationId?: string;
280
+ session?: ClientSession;
281
+ };
282
+ }
283
+ /**
284
+ * @deprecated Use createPayrollInstance() instead.
285
+ * Get or create the default container instance.
286
+ */
287
+ declare function getContainer(): Container;
288
+ /**
289
+ * @deprecated Use createPayrollInstance() instead.
290
+ * Initialize the default container.
291
+ */
292
+ declare function initializeContainer(config: ContainerConfig): void;
293
+ /**
294
+ * @deprecated Use container.isInitialized() instead.
295
+ * Check if the default container is initialized.
296
+ */
297
+ declare function isContainerInitialized(): boolean;
298
+ /**
299
+ * @deprecated Use container.getModels() instead.
300
+ * Get models from the default container.
301
+ */
302
+ declare function getModels(): ModelsContainer;
303
+ /**
304
+ * @deprecated Use container.getConfig() instead.
305
+ * Get config from the default container.
306
+ */
307
+ declare function getConfig(): HRMConfig;
308
+ /**
309
+ * @deprecated Use container.isSingleTenant() instead.
310
+ * Check if single-tenant mode.
311
+ */
312
+ declare function isSingleTenant(): boolean;
313
+
314
+ export { Container, type ContainerConfig, type Err, type ModelsContainer, type Ok, Result, ResultClass, all, err, flatMap, fromNullable, fromPromise, getConfig, getContainer, getModels, initializeContainer, isContainerInitialized, isErr, isOk, isSingleTenant, map, mapErr, match, ok, tryCatch, tryCatchSync, unwrap, unwrapOr, unwrapOrElse };