@classytic/payroll 2.0.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of @classytic/payroll might be problematic. Click here for more details.
- package/README.md +2599 -253
- package/dist/calculators/index.d.ts +433 -0
- package/dist/calculators/index.js +283 -0
- package/dist/calculators/index.js.map +1 -0
- package/dist/core/index.d.ts +85 -251
- package/dist/core/index.js +286 -91
- package/dist/core/index.js.map +1 -1
- package/dist/employee-identity-DXhgOgXE.d.ts +473 -0
- package/dist/employee.factory-BlZqhiCk.d.ts +189 -0
- package/dist/idempotency-Cw2CWicb.d.ts +52 -0
- package/dist/index.d.ts +618 -683
- package/dist/index.js +8336 -3580
- package/dist/index.js.map +1 -1
- package/dist/jurisdiction/index.d.ts +660 -0
- package/dist/jurisdiction/index.js +533 -0
- package/dist/jurisdiction/index.js.map +1 -0
- package/dist/payroll.d.ts +261 -65
- package/dist/payroll.js +4164 -1075
- package/dist/payroll.js.map +1 -1
- package/dist/schemas/index.d.ts +1176 -783
- package/dist/schemas/index.js +368 -28
- package/dist/schemas/index.js.map +1 -1
- package/dist/services/index.d.ts +582 -3
- package/dist/services/index.js +572 -96
- package/dist/services/index.js.map +1 -1
- package/dist/shift-compliance/index.d.ts +1171 -0
- package/dist/shift-compliance/index.js +1479 -0
- package/dist/shift-compliance/index.js.map +1 -0
- package/dist/types-BN3K_Uhr.d.ts +1842 -0
- package/dist/utils/index.d.ts +22 -2
- package/dist/utils/index.js +470 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +24 -6
- package/dist/index-CTjHlCzz.d.ts +0 -721
- package/dist/plugin-D9mOr3_d.d.ts +0 -333
- package/dist/types-BSYyX2KJ.d.ts +0 -671
|
@@ -0,0 +1 @@
|
|
|
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"]}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
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';
|
|
2
4
|
import { Model, ClientSession } from 'mongoose';
|
|
3
|
-
import { n as HRMConfig, S as SingleTenantConfig, o as Logger } from '../types-BSYyX2KJ.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @classytic/payroll - Result Type
|
|
@@ -128,70 +129,108 @@ declare const Result: {
|
|
|
128
129
|
/**
|
|
129
130
|
* @classytic/payroll - Dependency Container
|
|
130
131
|
*
|
|
131
|
-
*
|
|
132
|
-
* Enables clean dependency injection and testing
|
|
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
|
|
133
140
|
*/
|
|
134
141
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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;
|
|
140
153
|
}
|
|
141
|
-
|
|
142
|
-
|
|
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>;
|
|
143
159
|
config?: Partial<HRMConfig>;
|
|
144
160
|
singleTenant?: SingleTenantConfig | null;
|
|
145
161
|
logger?: Logger;
|
|
146
162
|
}
|
|
147
|
-
|
|
148
|
-
|
|
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> {
|
|
149
184
|
private _models;
|
|
150
185
|
private _config;
|
|
151
186
|
private _singleTenant;
|
|
152
187
|
private _logger;
|
|
153
188
|
private _initialized;
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Get singleton instance
|
|
157
|
-
*/
|
|
158
|
-
static getInstance(): Container;
|
|
159
|
-
/**
|
|
160
|
-
* Reset instance (for testing)
|
|
161
|
-
*/
|
|
162
|
-
static resetInstance(): void;
|
|
189
|
+
constructor();
|
|
163
190
|
/**
|
|
164
191
|
* Initialize container with configuration
|
|
165
192
|
*/
|
|
166
|
-
initialize(config: ContainerConfig): void;
|
|
193
|
+
initialize(config: ContainerConfig<TEmployee, TPayrollRecord, TTransaction, TAttendance, TLeaveRequest, TTaxWithholding>): void;
|
|
167
194
|
/**
|
|
168
195
|
* Check if container is initialized
|
|
169
196
|
*/
|
|
170
197
|
isInitialized(): boolean;
|
|
198
|
+
/**
|
|
199
|
+
* Reset container (useful for testing)
|
|
200
|
+
*/
|
|
201
|
+
reset(): void;
|
|
171
202
|
/**
|
|
172
203
|
* Ensure container is initialized
|
|
173
204
|
*/
|
|
174
205
|
private ensureInitialized;
|
|
175
206
|
/**
|
|
176
|
-
* Get models container
|
|
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)
|
|
177
216
|
*/
|
|
178
|
-
|
|
217
|
+
getPayrollRecordModel(): Model<TPayrollRecord>;
|
|
179
218
|
/**
|
|
180
|
-
* Get
|
|
219
|
+
* Get Transaction model (strongly typed)
|
|
181
220
|
*/
|
|
182
|
-
|
|
221
|
+
getTransactionModel(): Model<TTransaction>;
|
|
183
222
|
/**
|
|
184
|
-
* Get
|
|
223
|
+
* Get Attendance model (optional, strongly typed)
|
|
185
224
|
*/
|
|
186
|
-
|
|
225
|
+
getAttendanceModel(): Model<TAttendance> | null;
|
|
187
226
|
/**
|
|
188
|
-
* Get
|
|
227
|
+
* Get LeaveRequest model (optional, strongly typed)
|
|
189
228
|
*/
|
|
190
|
-
|
|
229
|
+
getLeaveRequestModel(): Model<TLeaveRequest> | null;
|
|
191
230
|
/**
|
|
192
|
-
* Get
|
|
231
|
+
* Get TaxWithholding model (optional, strongly typed)
|
|
193
232
|
*/
|
|
194
|
-
|
|
233
|
+
getTaxWithholdingModel(): Model<TTaxWithholding> | null;
|
|
195
234
|
/**
|
|
196
235
|
* Get configuration
|
|
197
236
|
*/
|
|
@@ -242,239 +281,34 @@ declare class Container {
|
|
|
242
281
|
};
|
|
243
282
|
}
|
|
244
283
|
/**
|
|
245
|
-
*
|
|
284
|
+
* @deprecated Use createPayrollInstance() instead.
|
|
285
|
+
* Get or create the default container instance.
|
|
246
286
|
*/
|
|
247
287
|
declare function getContainer(): Container;
|
|
248
288
|
/**
|
|
249
|
-
*
|
|
289
|
+
* @deprecated Use createPayrollInstance() instead.
|
|
290
|
+
* Initialize the default container.
|
|
250
291
|
*/
|
|
251
292
|
declare function initializeContainer(config: ContainerConfig): void;
|
|
252
293
|
/**
|
|
253
|
-
*
|
|
294
|
+
* @deprecated Use container.isInitialized() instead.
|
|
295
|
+
* Check if the default container is initialized.
|
|
254
296
|
*/
|
|
255
297
|
declare function isContainerInitialized(): boolean;
|
|
256
298
|
/**
|
|
257
|
-
*
|
|
299
|
+
* @deprecated Use container.getModels() instead.
|
|
300
|
+
* Get models from the default container.
|
|
258
301
|
*/
|
|
259
302
|
declare function getModels(): ModelsContainer;
|
|
260
303
|
/**
|
|
261
|
-
*
|
|
304
|
+
* @deprecated Use container.getConfig() instead.
|
|
305
|
+
* Get config from the default container.
|
|
262
306
|
*/
|
|
263
307
|
declare function getConfig(): HRMConfig;
|
|
264
308
|
/**
|
|
265
|
-
*
|
|
309
|
+
* @deprecated Use container.isSingleTenant() instead.
|
|
310
|
+
* Check if single-tenant mode.
|
|
266
311
|
*/
|
|
267
312
|
declare function isSingleTenant(): boolean;
|
|
268
313
|
|
|
269
|
-
|
|
270
|
-
* @classytic/payroll - Configuration & Calculation Utilities
|
|
271
|
-
*
|
|
272
|
-
* DESIGN PRINCIPLES:
|
|
273
|
-
* 1. Accept data, don't manage it
|
|
274
|
-
* 2. Pure functions - easy to test, no side effects
|
|
275
|
-
* 3. Smart defaults that work out of the box
|
|
276
|
-
* 4. Override at operation time when needed
|
|
277
|
-
*
|
|
278
|
-
* The payroll package CALCULATES, it doesn't STORE calendars/holidays.
|
|
279
|
-
* Your app manages that data and passes it when needed.
|
|
280
|
-
*/
|
|
281
|
-
/** Work schedule configuration */
|
|
282
|
-
interface WorkSchedule {
|
|
283
|
-
/** Working days (0=Sun, 1=Mon, ..., 6=Sat). Default: Mon-Fri */
|
|
284
|
-
workDays: number[];
|
|
285
|
-
/** Hours per work day. Default: 8 */
|
|
286
|
-
hoursPerDay: number;
|
|
287
|
-
}
|
|
288
|
-
/** Options passed when processing payroll */
|
|
289
|
-
interface PayrollProcessingOptions {
|
|
290
|
-
/** Holidays in this period (from YOUR app's holiday model) */
|
|
291
|
-
holidays?: Date[];
|
|
292
|
-
/** Override work schedule for this operation */
|
|
293
|
-
workSchedule?: Partial<WorkSchedule>;
|
|
294
|
-
/** Skip tax calculation */
|
|
295
|
-
skipTax?: boolean;
|
|
296
|
-
/** Skip proration (pay full amount regardless of hire/termination date) */
|
|
297
|
-
skipProration?: boolean;
|
|
298
|
-
/** Skip attendance deduction */
|
|
299
|
-
skipAttendance?: boolean;
|
|
300
|
-
}
|
|
301
|
-
/** Working days calculation result */
|
|
302
|
-
interface WorkingDaysResult {
|
|
303
|
-
/** Total calendar days in period */
|
|
304
|
-
totalDays: number;
|
|
305
|
-
/** Working days (excluding weekends and holidays) */
|
|
306
|
-
workingDays: number;
|
|
307
|
-
/** Weekend days */
|
|
308
|
-
weekends: number;
|
|
309
|
-
/** Holiday count */
|
|
310
|
-
holidays: number;
|
|
311
|
-
}
|
|
312
|
-
/** Proration calculation result */
|
|
313
|
-
interface ProrationResult {
|
|
314
|
-
/** Proration ratio (0-1) */
|
|
315
|
-
ratio: number;
|
|
316
|
-
/** Reason for proration */
|
|
317
|
-
reason: 'full' | 'new_hire' | 'termination' | 'both';
|
|
318
|
-
/** Whether salary should be prorated */
|
|
319
|
-
isProrated: boolean;
|
|
320
|
-
}
|
|
321
|
-
/** Tax calculation result */
|
|
322
|
-
interface TaxResult {
|
|
323
|
-
/** Tax amount */
|
|
324
|
-
amount: number;
|
|
325
|
-
/** Effective tax rate */
|
|
326
|
-
effectiveRate: number;
|
|
327
|
-
}
|
|
328
|
-
/** Attendance data (from YOUR attendance system) */
|
|
329
|
-
interface AttendanceInput {
|
|
330
|
-
/** Expected work days in period */
|
|
331
|
-
expectedDays: number;
|
|
332
|
-
/** Actual days worked */
|
|
333
|
-
actualDays: number;
|
|
334
|
-
}
|
|
335
|
-
/** Complete salary calculation result */
|
|
336
|
-
interface SalaryCalculationResult {
|
|
337
|
-
/** Original base salary */
|
|
338
|
-
baseSalary: number;
|
|
339
|
-
/** Prorated base salary */
|
|
340
|
-
proratedBase: number;
|
|
341
|
-
/** Total allowances */
|
|
342
|
-
totalAllowances: number;
|
|
343
|
-
/** Total deductions (excluding tax) */
|
|
344
|
-
totalDeductions: number;
|
|
345
|
-
/** Attendance deduction */
|
|
346
|
-
attendanceDeduction: number;
|
|
347
|
-
/** Gross salary (prorated base + allowances) */
|
|
348
|
-
grossSalary: number;
|
|
349
|
-
/** Tax amount */
|
|
350
|
-
taxAmount: number;
|
|
351
|
-
/** Net salary (gross - all deductions - tax) */
|
|
352
|
-
netSalary: number;
|
|
353
|
-
/** Proration details */
|
|
354
|
-
proration: ProrationResult;
|
|
355
|
-
/** Working days details */
|
|
356
|
-
workingDays: WorkingDaysResult;
|
|
357
|
-
/** Itemized breakdown */
|
|
358
|
-
breakdown: {
|
|
359
|
-
allowances: Array<{
|
|
360
|
-
type: string;
|
|
361
|
-
amount: number;
|
|
362
|
-
taxable: boolean;
|
|
363
|
-
}>;
|
|
364
|
-
deductions: Array<{
|
|
365
|
-
type: string;
|
|
366
|
-
amount: number;
|
|
367
|
-
}>;
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
declare const COUNTRY_DEFAULTS: Record<string, {
|
|
371
|
-
currency: string;
|
|
372
|
-
workDays: number[];
|
|
373
|
-
taxBrackets: Array<{
|
|
374
|
-
min: number;
|
|
375
|
-
max: number;
|
|
376
|
-
rate: number;
|
|
377
|
-
}>;
|
|
378
|
-
}>;
|
|
379
|
-
declare const DEFAULT_WORK_SCHEDULE: WorkSchedule;
|
|
380
|
-
declare const DEFAULT_TAX_BRACKETS: {
|
|
381
|
-
min: number;
|
|
382
|
-
max: number;
|
|
383
|
-
rate: number;
|
|
384
|
-
}[];
|
|
385
|
-
/**
|
|
386
|
-
* Count working days in a date range
|
|
387
|
-
*
|
|
388
|
-
* @example
|
|
389
|
-
* const result = countWorkingDays(
|
|
390
|
-
* new Date('2024-03-01'),
|
|
391
|
-
* new Date('2024-03-31'),
|
|
392
|
-
* { workDays: [1,2,3,4,5], holidays: companyHolidays }
|
|
393
|
-
* );
|
|
394
|
-
*/
|
|
395
|
-
declare function countWorkingDays(startDate: Date, endDate: Date, options?: {
|
|
396
|
-
workDays?: number[];
|
|
397
|
-
holidays?: Date[];
|
|
398
|
-
}): WorkingDaysResult;
|
|
399
|
-
/**
|
|
400
|
-
* Calculate proration ratio for partial months
|
|
401
|
-
*
|
|
402
|
-
* @example
|
|
403
|
-
* const proration = calculateProration(
|
|
404
|
-
* employee.hireDate,
|
|
405
|
-
* employee.terminationDate,
|
|
406
|
-
* periodStart,
|
|
407
|
-
* periodEnd
|
|
408
|
-
* );
|
|
409
|
-
*/
|
|
410
|
-
declare function calculateProration(hireDate: Date, terminationDate: Date | null | undefined, periodStart: Date, periodEnd: Date): ProrationResult;
|
|
411
|
-
/**
|
|
412
|
-
* Calculate tax using brackets (annualized)
|
|
413
|
-
*
|
|
414
|
-
* @example
|
|
415
|
-
* const tax = calculateTax(monthlyIncome, 'USD');
|
|
416
|
-
*/
|
|
417
|
-
declare function calculateTax(monthlyIncome: number, currency: string, customBrackets?: Array<{
|
|
418
|
-
min: number;
|
|
419
|
-
max: number;
|
|
420
|
-
rate: number;
|
|
421
|
-
}>): TaxResult;
|
|
422
|
-
/**
|
|
423
|
-
* Calculate attendance deduction
|
|
424
|
-
*
|
|
425
|
-
* @example
|
|
426
|
-
* const deduction = calculateAttendanceDeduction(22, 20, dailyRate);
|
|
427
|
-
*/
|
|
428
|
-
declare function calculateAttendanceDeduction(expectedDays: number, actualDays: number, dailyRate: number, maxDeductionPercent?: number): number;
|
|
429
|
-
/**
|
|
430
|
-
* Calculate complete salary breakdown
|
|
431
|
-
*
|
|
432
|
-
* This is the main function for salary calculation.
|
|
433
|
-
* Pass all data from YOUR app, get back complete breakdown.
|
|
434
|
-
*
|
|
435
|
-
* @example
|
|
436
|
-
* const result = calculateSalaryBreakdown({
|
|
437
|
-
* baseSalary: 100000,
|
|
438
|
-
* currency: 'USD',
|
|
439
|
-
* hireDate: employee.hireDate,
|
|
440
|
-
* terminationDate: employee.terminationDate,
|
|
441
|
-
* periodStart: new Date('2024-03-01'),
|
|
442
|
-
* periodEnd: new Date('2024-03-31'),
|
|
443
|
-
* allowances: [{ type: 'housing', amount: 20000, taxable: true }],
|
|
444
|
-
* deductions: [{ type: 'provident_fund', amount: 5000 }],
|
|
445
|
-
* options: { holidays: companyHolidays },
|
|
446
|
-
* attendance: { expectedDays: 22, actualDays: 20 },
|
|
447
|
-
* });
|
|
448
|
-
*/
|
|
449
|
-
declare function calculateSalaryBreakdown(params: {
|
|
450
|
-
baseSalary: number;
|
|
451
|
-
currency: string;
|
|
452
|
-
hireDate: Date;
|
|
453
|
-
terminationDate?: Date | null;
|
|
454
|
-
periodStart: Date;
|
|
455
|
-
periodEnd: Date;
|
|
456
|
-
allowances?: Array<{
|
|
457
|
-
type: string;
|
|
458
|
-
amount: number;
|
|
459
|
-
taxable?: boolean;
|
|
460
|
-
}>;
|
|
461
|
-
deductions?: Array<{
|
|
462
|
-
type: string;
|
|
463
|
-
amount: number;
|
|
464
|
-
}>;
|
|
465
|
-
options?: PayrollProcessingOptions;
|
|
466
|
-
attendance?: AttendanceInput;
|
|
467
|
-
}): SalaryCalculationResult;
|
|
468
|
-
/**
|
|
469
|
-
* Get pay period dates for a given month
|
|
470
|
-
*
|
|
471
|
-
* @example
|
|
472
|
-
* const period = getPayPeriod(3, 2024); // March 2024
|
|
473
|
-
*/
|
|
474
|
-
declare function getPayPeriod(month: number, year: number, payDay?: number): {
|
|
475
|
-
startDate: Date;
|
|
476
|
-
endDate: Date;
|
|
477
|
-
payDate: Date;
|
|
478
|
-
};
|
|
479
|
-
|
|
480
|
-
export { type AttendanceInput, COUNTRY_DEFAULTS, Container, type ContainerConfig, DEFAULT_TAX_BRACKETS, DEFAULT_WORK_SCHEDULE, type Err, type ModelsContainer, type Ok, type PayrollProcessingOptions, type ProrationResult, Result, ResultClass, type SalaryCalculationResult, type TaxResult, type WorkSchedule, type WorkingDaysResult, all, calculateAttendanceDeduction, calculateProration, calculateSalaryBreakdown, calculateTax, countWorkingDays, err, flatMap, fromNullable, fromPromise, getConfig, getContainer, getModels, getPayPeriod, initializeContainer, isContainerInitialized, isErr, isOk, isSingleTenant, map, mapErr, match, ok, tryCatch, tryCatchSync, unwrap, unwrapOr, unwrapOrElse };
|
|
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 };
|