@classytic/payroll 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +168 -489
  2. package/dist/core/index.d.ts +480 -0
  3. package/dist/core/index.js +971 -0
  4. package/dist/core/index.js.map +1 -0
  5. package/dist/index-CTjHlCzz.d.ts +721 -0
  6. package/dist/index.d.ts +967 -0
  7. package/dist/index.js +4352 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/payroll.d.ts +233 -0
  10. package/dist/payroll.js +2103 -0
  11. package/dist/payroll.js.map +1 -0
  12. package/dist/plugin-D9mOr3_d.d.ts +333 -0
  13. package/dist/schemas/index.d.ts +2869 -0
  14. package/dist/schemas/index.js +440 -0
  15. package/dist/schemas/index.js.map +1 -0
  16. package/dist/services/index.d.ts +3 -0
  17. package/dist/services/index.js +1696 -0
  18. package/dist/services/index.js.map +1 -0
  19. package/dist/types-BSYyX2KJ.d.ts +671 -0
  20. package/dist/utils/index.d.ts +873 -0
  21. package/dist/utils/index.js +1046 -0
  22. package/dist/utils/index.js.map +1 -0
  23. package/package.json +54 -37
  24. package/dist/types/config.d.ts +0 -162
  25. package/dist/types/core/compensation.manager.d.ts +0 -54
  26. package/dist/types/core/employment.manager.d.ts +0 -49
  27. package/dist/types/core/payroll.manager.d.ts +0 -60
  28. package/dist/types/enums.d.ts +0 -117
  29. package/dist/types/factories/compensation.factory.d.ts +0 -196
  30. package/dist/types/factories/employee.factory.d.ts +0 -149
  31. package/dist/types/factories/payroll.factory.d.ts +0 -319
  32. package/dist/types/hrm.orchestrator.d.ts +0 -47
  33. package/dist/types/index.d.ts +0 -20
  34. package/dist/types/init.d.ts +0 -30
  35. package/dist/types/models/payroll-record.model.d.ts +0 -3
  36. package/dist/types/plugins/employee.plugin.d.ts +0 -2
  37. package/dist/types/schemas/employment.schema.d.ts +0 -959
  38. package/dist/types/services/compensation.service.d.ts +0 -94
  39. package/dist/types/services/employee.service.d.ts +0 -28
  40. package/dist/types/services/payroll.service.d.ts +0 -30
  41. package/dist/types/utils/calculation.utils.d.ts +0 -26
  42. package/dist/types/utils/date.utils.d.ts +0 -35
  43. package/dist/types/utils/logger.d.ts +0 -12
  44. package/dist/types/utils/query-builders.d.ts +0 -83
  45. package/dist/types/utils/validation.utils.d.ts +0 -33
  46. package/payroll.d.ts +0 -241
  47. package/src/config.js +0 -177
  48. package/src/core/compensation.manager.js +0 -242
  49. package/src/core/employment.manager.js +0 -224
  50. package/src/core/payroll.manager.js +0 -499
  51. package/src/enums.js +0 -141
  52. package/src/factories/compensation.factory.js +0 -198
  53. package/src/factories/employee.factory.js +0 -173
  54. package/src/factories/payroll.factory.js +0 -413
  55. package/src/hrm.orchestrator.js +0 -139
  56. package/src/index.js +0 -172
  57. package/src/init.js +0 -62
  58. package/src/models/payroll-record.model.js +0 -126
  59. package/src/plugins/employee.plugin.js +0 -164
  60. package/src/schemas/employment.schema.js +0 -126
  61. package/src/services/compensation.service.js +0 -231
  62. package/src/services/employee.service.js +0 -162
  63. package/src/services/payroll.service.js +0 -213
  64. package/src/utils/calculation.utils.js +0 -91
  65. package/src/utils/date.utils.js +0 -120
  66. package/src/utils/logger.js +0 -36
  67. package/src/utils/query-builders.js +0 -185
  68. package/src/utils/validation.utils.js +0 -122
@@ -0,0 +1,1046 @@
1
+ import { Types } from 'mongoose';
2
+
3
+ // src/utils/logger.ts
4
+ var createConsoleLogger = () => ({
5
+ info: (message, meta) => {
6
+ if (meta) {
7
+ console.log(`[Payroll] INFO: ${message}`, meta);
8
+ } else {
9
+ console.log(`[Payroll] INFO: ${message}`);
10
+ }
11
+ },
12
+ error: (message, meta) => {
13
+ if (meta) {
14
+ console.error(`[Payroll] ERROR: ${message}`, meta);
15
+ } else {
16
+ console.error(`[Payroll] ERROR: ${message}`);
17
+ }
18
+ },
19
+ warn: (message, meta) => {
20
+ if (meta) {
21
+ console.warn(`[Payroll] WARN: ${message}`, meta);
22
+ } else {
23
+ console.warn(`[Payroll] WARN: ${message}`);
24
+ }
25
+ },
26
+ debug: (message, meta) => {
27
+ if (process.env.NODE_ENV !== "production") {
28
+ if (meta) {
29
+ console.log(`[Payroll] DEBUG: ${message}`, meta);
30
+ } else {
31
+ console.log(`[Payroll] DEBUG: ${message}`);
32
+ }
33
+ }
34
+ }
35
+ });
36
+ var currentLogger = createConsoleLogger();
37
+ var loggingEnabled = true;
38
+ function getLogger() {
39
+ return currentLogger;
40
+ }
41
+ function setLogger(logger2) {
42
+ currentLogger = logger2;
43
+ }
44
+ function resetLogger() {
45
+ currentLogger = createConsoleLogger();
46
+ }
47
+ function createChildLogger(prefix) {
48
+ const parent = currentLogger;
49
+ return {
50
+ info: (message, meta) => parent.info(`[${prefix}] ${message}`, meta),
51
+ error: (message, meta) => parent.error(`[${prefix}] ${message}`, meta),
52
+ warn: (message, meta) => parent.warn(`[${prefix}] ${message}`, meta),
53
+ debug: (message, meta) => parent.debug(`[${prefix}] ${message}`, meta)
54
+ };
55
+ }
56
+ function createSilentLogger() {
57
+ return {
58
+ info: () => {
59
+ },
60
+ error: () => {
61
+ },
62
+ warn: () => {
63
+ },
64
+ debug: () => {
65
+ }
66
+ };
67
+ }
68
+ function enableLogging() {
69
+ loggingEnabled = true;
70
+ }
71
+ function disableLogging() {
72
+ loggingEnabled = false;
73
+ }
74
+ function isLoggingEnabled() {
75
+ return loggingEnabled;
76
+ }
77
+ var logger = {
78
+ info: (message, meta) => {
79
+ if (loggingEnabled) currentLogger.info(message, meta);
80
+ },
81
+ error: (message, meta) => {
82
+ if (loggingEnabled) currentLogger.error(message, meta);
83
+ },
84
+ warn: (message, meta) => {
85
+ if (loggingEnabled) currentLogger.warn(message, meta);
86
+ },
87
+ debug: (message, meta) => {
88
+ if (loggingEnabled) currentLogger.debug(message, meta);
89
+ }
90
+ };
91
+
92
+ // src/utils/date.ts
93
+ function addDays(date, days) {
94
+ const result = new Date(date);
95
+ result.setDate(result.getDate() + days);
96
+ return result;
97
+ }
98
+ function addMonths(date, months) {
99
+ const result = new Date(date);
100
+ result.setMonth(result.getMonth() + months);
101
+ return result;
102
+ }
103
+ function addYears(date, years) {
104
+ const result = new Date(date);
105
+ result.setFullYear(result.getFullYear() + years);
106
+ return result;
107
+ }
108
+ function subDays(date, days) {
109
+ return addDays(date, -days);
110
+ }
111
+ function subMonths(date, months) {
112
+ return addMonths(date, -months);
113
+ }
114
+ function startOfMonth(date) {
115
+ const result = new Date(date);
116
+ result.setDate(1);
117
+ result.setHours(0, 0, 0, 0);
118
+ return result;
119
+ }
120
+ function endOfMonth(date) {
121
+ const result = new Date(date);
122
+ result.setMonth(result.getMonth() + 1, 0);
123
+ result.setHours(23, 59, 59, 999);
124
+ return result;
125
+ }
126
+ function startOfYear(date) {
127
+ const result = new Date(date);
128
+ result.setMonth(0, 1);
129
+ result.setHours(0, 0, 0, 0);
130
+ return result;
131
+ }
132
+ function endOfYear(date) {
133
+ const result = new Date(date);
134
+ result.setMonth(11, 31);
135
+ result.setHours(23, 59, 59, 999);
136
+ return result;
137
+ }
138
+ function startOfDay(date) {
139
+ const result = new Date(date);
140
+ result.setHours(0, 0, 0, 0);
141
+ return result;
142
+ }
143
+ function endOfDay(date) {
144
+ const result = new Date(date);
145
+ result.setHours(23, 59, 59, 999);
146
+ return result;
147
+ }
148
+ function diffInDays(start, end) {
149
+ return Math.ceil(
150
+ (new Date(end).getTime() - new Date(start).getTime()) / (1e3 * 60 * 60 * 24)
151
+ );
152
+ }
153
+ function diffInMonths(start, end) {
154
+ const startDate = new Date(start);
155
+ const endDate = new Date(end);
156
+ return (endDate.getFullYear() - startDate.getFullYear()) * 12 + (endDate.getMonth() - startDate.getMonth());
157
+ }
158
+ function diffInYears(start, end) {
159
+ return Math.floor(diffInMonths(start, end) / 12);
160
+ }
161
+ var daysBetween = diffInDays;
162
+ var monthsBetween = diffInMonths;
163
+ function isWeekday(date) {
164
+ const day = new Date(date).getDay();
165
+ return day >= 1 && day <= 5;
166
+ }
167
+ function isWeekend(date) {
168
+ const day = new Date(date).getDay();
169
+ return day === 0 || day === 6;
170
+ }
171
+ function getDayOfWeek(date) {
172
+ return new Date(date).getDay();
173
+ }
174
+ function getDayName(date) {
175
+ const days = [
176
+ "Sunday",
177
+ "Monday",
178
+ "Tuesday",
179
+ "Wednesday",
180
+ "Thursday",
181
+ "Friday",
182
+ "Saturday"
183
+ ];
184
+ return days[getDayOfWeek(date)];
185
+ }
186
+ function getPayPeriod(month, year) {
187
+ const startDate = new Date(year, month - 1, 1);
188
+ return {
189
+ month,
190
+ year,
191
+ startDate: startOfMonth(startDate),
192
+ endDate: endOfMonth(startDate)
193
+ };
194
+ }
195
+ function getCurrentPeriod(date = /* @__PURE__ */ new Date()) {
196
+ const d = new Date(date);
197
+ return {
198
+ year: d.getFullYear(),
199
+ month: d.getMonth() + 1
200
+ };
201
+ }
202
+ function getWorkingDaysInMonth(year, month) {
203
+ const start = new Date(year, month - 1, 1);
204
+ const end = endOfMonth(start);
205
+ let count = 0;
206
+ const current = new Date(start);
207
+ while (current <= end) {
208
+ if (isWeekday(current)) {
209
+ count++;
210
+ }
211
+ current.setDate(current.getDate() + 1);
212
+ }
213
+ return count;
214
+ }
215
+ function getDaysInMonth(year, month) {
216
+ return new Date(year, month, 0).getDate();
217
+ }
218
+ function calculateProbationEnd(hireDate, probationMonths) {
219
+ if (!probationMonths || probationMonths <= 0) return null;
220
+ return addMonths(hireDate, probationMonths);
221
+ }
222
+ function isOnProbation(probationEndDate, now = /* @__PURE__ */ new Date()) {
223
+ if (!probationEndDate) return false;
224
+ return now < new Date(probationEndDate);
225
+ }
226
+ function calculateYearsOfService(hireDate, terminationDate) {
227
+ const end = terminationDate || /* @__PURE__ */ new Date();
228
+ const days = diffInDays(hireDate, end);
229
+ return Math.max(0, Math.floor(days / 365.25 * 10) / 10);
230
+ }
231
+ function isDateInRange(date, start, end) {
232
+ const checkDate = new Date(date);
233
+ return checkDate >= new Date(start) && checkDate <= new Date(end);
234
+ }
235
+ function getPayPeriodDateRange(month, year) {
236
+ const period = getPayPeriod(month, year);
237
+ return { start: period.startDate, end: period.endDate };
238
+ }
239
+ function formatDateForDB(date) {
240
+ if (!date) return "";
241
+ return new Date(date).toISOString();
242
+ }
243
+ function parseDBDate(dateString) {
244
+ if (!dateString) return null;
245
+ return new Date(dateString);
246
+ }
247
+ function formatPeriod({ month, year }) {
248
+ return `${String(month).padStart(2, "0")}/${year}`;
249
+ }
250
+ function parsePeriod(periodString) {
251
+ const [month, year] = periodString.split("/").map(Number);
252
+ return { month, year };
253
+ }
254
+ function getMonthName(month) {
255
+ const months = [
256
+ "January",
257
+ "February",
258
+ "March",
259
+ "April",
260
+ "May",
261
+ "June",
262
+ "July",
263
+ "August",
264
+ "September",
265
+ "October",
266
+ "November",
267
+ "December"
268
+ ];
269
+ return months[month - 1] || "";
270
+ }
271
+ function getShortMonthName(month) {
272
+ const months = [
273
+ "Jan",
274
+ "Feb",
275
+ "Mar",
276
+ "Apr",
277
+ "May",
278
+ "Jun",
279
+ "Jul",
280
+ "Aug",
281
+ "Sep",
282
+ "Oct",
283
+ "Nov",
284
+ "Dec"
285
+ ];
286
+ return months[month - 1] || "";
287
+ }
288
+ var date_default = {
289
+ addDays,
290
+ addMonths,
291
+ addYears,
292
+ subDays,
293
+ subMonths,
294
+ startOfMonth,
295
+ endOfMonth,
296
+ startOfYear,
297
+ endOfYear,
298
+ startOfDay,
299
+ endOfDay,
300
+ diffInDays,
301
+ diffInMonths,
302
+ diffInYears,
303
+ daysBetween,
304
+ monthsBetween,
305
+ isWeekday,
306
+ isWeekend,
307
+ getDayOfWeek,
308
+ getDayName,
309
+ getPayPeriod,
310
+ getCurrentPeriod,
311
+ getWorkingDaysInMonth,
312
+ getDaysInMonth,
313
+ calculateProbationEnd,
314
+ isOnProbation,
315
+ calculateYearsOfService,
316
+ isDateInRange,
317
+ getPayPeriodDateRange,
318
+ formatDateForDB,
319
+ parseDBDate,
320
+ formatPeriod,
321
+ parsePeriod,
322
+ getMonthName,
323
+ getShortMonthName
324
+ };
325
+
326
+ // src/utils/calculation.ts
327
+ function sum(numbers) {
328
+ return numbers.reduce((total, n) => total + n, 0);
329
+ }
330
+ function sumBy(items, getter) {
331
+ return items.reduce((total, item) => total + getter(item), 0);
332
+ }
333
+ function sumAllowances(allowances) {
334
+ return sumBy(allowances, (a) => a.amount);
335
+ }
336
+ function sumDeductions(deductions) {
337
+ return sumBy(deductions, (d) => d.amount);
338
+ }
339
+ function applyPercentage(amount, percentage) {
340
+ return Math.round(amount * (percentage / 100));
341
+ }
342
+ function calculatePercentage(part, total) {
343
+ return total > 0 ? Math.round(part / total * 100) : 0;
344
+ }
345
+ function roundTo(value, decimals = 2) {
346
+ const factor = Math.pow(10, decimals);
347
+ return Math.round(value * factor) / factor;
348
+ }
349
+ function calculateGross(baseAmount, allowances) {
350
+ return baseAmount + sumAllowances(allowances);
351
+ }
352
+ function calculateNet(gross, deductions) {
353
+ return Math.max(0, gross - sumDeductions(deductions));
354
+ }
355
+ function calculateTotalCompensation(baseAmount, allowances, deductions) {
356
+ const gross = calculateGross(baseAmount, allowances);
357
+ const totalDeductions = sumDeductions(deductions);
358
+ const net = calculateNet(gross, deductions);
359
+ return { gross, net, deductions: totalDeductions };
360
+ }
361
+ function calculateAllowanceAmount(allowance, baseAmount) {
362
+ if (allowance.isPercentage && allowance.value !== void 0) {
363
+ return applyPercentage(baseAmount, allowance.value);
364
+ }
365
+ return allowance.amount;
366
+ }
367
+ function calculateDeductionAmount(deduction, baseAmount) {
368
+ if (deduction.isPercentage && deduction.value !== void 0) {
369
+ return applyPercentage(baseAmount, deduction.value);
370
+ }
371
+ return deduction.amount;
372
+ }
373
+ function calculateAllowances(allowances, baseAmount) {
374
+ return allowances.map((allowance) => ({
375
+ ...allowance,
376
+ calculatedAmount: calculateAllowanceAmount(allowance, baseAmount)
377
+ }));
378
+ }
379
+ function calculateDeductions(deductions, baseAmount) {
380
+ return deductions.map((deduction) => ({
381
+ ...deduction,
382
+ calculatedAmount: calculateDeductionAmount(deduction, baseAmount)
383
+ }));
384
+ }
385
+ function calculateCompensationBreakdown(compensation) {
386
+ const { baseAmount, allowances = [], deductions = [] } = compensation;
387
+ const calculatedAllowances = calculateAllowances(allowances, baseAmount);
388
+ const calculatedDeductions = calculateDeductions(deductions, baseAmount);
389
+ const grossAmount = baseAmount + sumBy(calculatedAllowances, (a) => a.calculatedAmount);
390
+ const netAmount = grossAmount - sumBy(calculatedDeductions, (d) => d.calculatedAmount);
391
+ return {
392
+ baseAmount,
393
+ allowances: calculatedAllowances,
394
+ deductions: calculatedDeductions,
395
+ grossAmount,
396
+ netAmount: Math.max(0, netAmount)
397
+ };
398
+ }
399
+ function calculateProRating(hireDate, periodStart, periodEnd) {
400
+ const totalDays = diffInDays(periodStart, periodEnd) + 1;
401
+ if (hireDate <= periodStart) {
402
+ return {
403
+ isProRated: false,
404
+ totalDays,
405
+ actualDays: totalDays,
406
+ ratio: 1
407
+ };
408
+ }
409
+ if (hireDate > periodStart && hireDate <= periodEnd) {
410
+ const actualDays = diffInDays(hireDate, periodEnd) + 1;
411
+ const ratio = actualDays / totalDays;
412
+ return {
413
+ isProRated: true,
414
+ totalDays,
415
+ actualDays,
416
+ ratio
417
+ };
418
+ }
419
+ return {
420
+ isProRated: false,
421
+ totalDays,
422
+ actualDays: 0,
423
+ ratio: 0
424
+ };
425
+ }
426
+ function applyProRating(amount, proRating) {
427
+ return Math.round(amount * proRating.ratio);
428
+ }
429
+ function calculateProRatedSalary(baseAmount, hireDate, period) {
430
+ const proRating = calculateProRating(hireDate, period.startDate, period.endDate);
431
+ const amount = applyProRating(baseAmount, proRating);
432
+ return { amount, proRating };
433
+ }
434
+ function applyTaxBrackets(amount, brackets) {
435
+ let tax = 0;
436
+ for (const bracket of brackets) {
437
+ if (amount > bracket.min) {
438
+ const taxableAmount = Math.min(amount, bracket.max) - bracket.min;
439
+ tax += taxableAmount * bracket.rate;
440
+ }
441
+ }
442
+ return Math.round(tax);
443
+ }
444
+ function calculateTax(amount, brackets) {
445
+ const tax = applyTaxBrackets(amount, brackets);
446
+ return {
447
+ gross: amount,
448
+ tax,
449
+ net: amount - tax
450
+ };
451
+ }
452
+ function pipe(...fns) {
453
+ return (value) => fns.reduce((acc, fn) => fn(acc), value);
454
+ }
455
+ function compose(...fns) {
456
+ return (value) => fns.reduceRight((acc, fn) => fn(acc), value);
457
+ }
458
+ function createAllowanceCalculator(allowances) {
459
+ return (baseSalary) => calculateAllowances(allowances, baseSalary);
460
+ }
461
+ function createDeductionCalculator(deductions) {
462
+ return (baseSalary) => calculateDeductions(deductions, baseSalary);
463
+ }
464
+ function calculateOvertime(hourlyRate, overtimeHours, multiplier = 1.5) {
465
+ return Math.round(hourlyRate * overtimeHours * multiplier);
466
+ }
467
+ function calculateHourlyRate(monthlySalary, hoursPerMonth = 176) {
468
+ return Math.round(monthlySalary / hoursPerMonth);
469
+ }
470
+ function calculateDailyRate(monthlySalary, daysPerMonth = 22) {
471
+ return Math.round(monthlySalary / daysPerMonth);
472
+ }
473
+ var calculation_default = {
474
+ sum,
475
+ sumBy,
476
+ sumAllowances,
477
+ sumDeductions,
478
+ applyPercentage,
479
+ calculatePercentage,
480
+ roundTo,
481
+ calculateGross,
482
+ calculateNet,
483
+ calculateTotalCompensation,
484
+ calculateAllowanceAmount,
485
+ calculateDeductionAmount,
486
+ calculateAllowances,
487
+ calculateDeductions,
488
+ calculateCompensationBreakdown,
489
+ calculateProRating,
490
+ applyProRating,
491
+ calculateProRatedSalary,
492
+ applyTaxBrackets,
493
+ calculateTax,
494
+ pipe,
495
+ compose,
496
+ createAllowanceCalculator,
497
+ createDeductionCalculator,
498
+ calculateOvertime,
499
+ calculateHourlyRate,
500
+ calculateDailyRate
501
+ };
502
+
503
+ // src/enums.ts
504
+ var EMPLOYMENT_TYPE = {
505
+ FULL_TIME: "full_time",
506
+ PART_TIME: "part_time",
507
+ CONTRACT: "contract",
508
+ INTERN: "intern",
509
+ CONSULTANT: "consultant"
510
+ };
511
+ var EMPLOYMENT_TYPE_VALUES = Object.values(EMPLOYMENT_TYPE);
512
+ var EMPLOYEE_STATUS = {
513
+ ACTIVE: "active",
514
+ ON_LEAVE: "on_leave",
515
+ SUSPENDED: "suspended",
516
+ TERMINATED: "terminated"
517
+ };
518
+ var EMPLOYEE_STATUS_VALUES = Object.values(EMPLOYEE_STATUS);
519
+
520
+ // src/utils/validation.ts
521
+ function isActive(employee2) {
522
+ return employee2?.status === "active";
523
+ }
524
+ function isOnLeave(employee2) {
525
+ return employee2?.status === "on_leave";
526
+ }
527
+ function isSuspended(employee2) {
528
+ return employee2?.status === "suspended";
529
+ }
530
+ function isTerminated(employee2) {
531
+ return employee2?.status === "terminated";
532
+ }
533
+ function isEmployed(employee2) {
534
+ return isActive(employee2) || isOnLeave(employee2) || isSuspended(employee2);
535
+ }
536
+ function canReceiveSalary(employee2) {
537
+ return (isActive(employee2) || isOnLeave(employee2)) && (employee2.compensation?.baseAmount ?? 0) > 0;
538
+ }
539
+ function canUpdateEmployment(employee2) {
540
+ return !isTerminated(employee2);
541
+ }
542
+ function hasCompensation(employee2) {
543
+ return (employee2.compensation?.baseAmount ?? 0) > 0;
544
+ }
545
+ function isValidCompensation(compensation) {
546
+ return !!(compensation?.baseAmount && compensation.baseAmount > 0 && compensation.frequency && compensation.currency);
547
+ }
548
+ function isValidBankDetails(bankDetails) {
549
+ return !!(bankDetails?.accountNumber && bankDetails.bankName && bankDetails.accountName);
550
+ }
551
+ function isInProbation(employee2, now = /* @__PURE__ */ new Date()) {
552
+ if (!employee2?.probationEndDate) return false;
553
+ return new Date(employee2.probationEndDate) > now;
554
+ }
555
+ function hasCompletedProbation(employee2, now = /* @__PURE__ */ new Date()) {
556
+ if (!employee2?.probationEndDate) return true;
557
+ return new Date(employee2.probationEndDate) <= now;
558
+ }
559
+ function isEligibleForBonus(employee2, requiredMonths = 6) {
560
+ if (!isActive(employee2) || !employee2.hireDate) return false;
561
+ const monthsEmployed = diffInMonths(employee2.hireDate, /* @__PURE__ */ new Date());
562
+ return monthsEmployed >= requiredMonths;
563
+ }
564
+ function isEligibleForPayroll(employee2) {
565
+ const reasons = [];
566
+ if (!isActive(employee2) && !isOnLeave(employee2)) {
567
+ reasons.push("Employee is not in active or on-leave status");
568
+ }
569
+ if (!hasCompensation(employee2)) {
570
+ reasons.push("Employee has no valid compensation");
571
+ }
572
+ return {
573
+ eligible: reasons.length === 0,
574
+ reasons
575
+ };
576
+ }
577
+ function required(fieldName) {
578
+ return (value) => value !== void 0 && value !== null && value !== "" ? true : `${fieldName} is required`;
579
+ }
580
+ function min(minValue2, fieldName) {
581
+ return (value) => value >= minValue2 ? true : `${fieldName} must be at least ${minValue2}`;
582
+ }
583
+ function max(maxValue2, fieldName) {
584
+ return (value) => value <= maxValue2 ? true : `${fieldName} must not exceed ${maxValue2}`;
585
+ }
586
+ function inRange(minValue2, maxValue2, fieldName) {
587
+ return (value) => value >= minValue2 && value <= maxValue2 ? true : `${fieldName} must be between ${minValue2} and ${maxValue2}`;
588
+ }
589
+ function isPositive(fieldName) {
590
+ return (value) => value > 0 ? true : `${fieldName} must be positive`;
591
+ }
592
+ function oneOf(allowedValues, fieldName) {
593
+ return (value) => allowedValues.includes(value) ? true : `${fieldName} must be one of: ${allowedValues.join(", ")}`;
594
+ }
595
+ function isValidStatus(value) {
596
+ return EMPLOYEE_STATUS_VALUES.includes(value);
597
+ }
598
+ function isValidEmploymentType(value) {
599
+ return EMPLOYMENT_TYPE_VALUES.includes(value);
600
+ }
601
+ function composeValidators(...validators) {
602
+ return (value, data) => {
603
+ for (const validator of validators) {
604
+ const result = validator(value, data);
605
+ if (result !== true) return result;
606
+ }
607
+ return true;
608
+ };
609
+ }
610
+ function createValidator(validationFns) {
611
+ return (data) => {
612
+ const errors = [];
613
+ for (const [field, validator] of Object.entries(validationFns)) {
614
+ const result = validator(data[field], data);
615
+ if (result !== true) {
616
+ errors.push(result);
617
+ }
618
+ }
619
+ return {
620
+ valid: errors.length === 0,
621
+ errors
622
+ };
623
+ };
624
+ }
625
+ function hasRequiredFields(obj, fields) {
626
+ const missing = fields.filter(
627
+ (field) => obj[field] === void 0 || obj[field] === null
628
+ );
629
+ return {
630
+ valid: missing.length === 0,
631
+ missing
632
+ };
633
+ }
634
+ var minValue = min;
635
+ var maxValue = max;
636
+ var isInRange = inRange;
637
+ var validation_default = {
638
+ // Status validators
639
+ isActive,
640
+ isOnLeave,
641
+ isSuspended,
642
+ isTerminated,
643
+ isEmployed,
644
+ canReceiveSalary,
645
+ canUpdateEmployment,
646
+ // Compensation validators
647
+ hasCompensation,
648
+ isValidCompensation,
649
+ isValidBankDetails,
650
+ // Probation validators
651
+ isInProbation,
652
+ hasCompletedProbation,
653
+ // Eligibility validators
654
+ isEligibleForBonus,
655
+ isEligibleForPayroll,
656
+ // Field validators
657
+ required,
658
+ min,
659
+ max,
660
+ inRange,
661
+ isPositive,
662
+ oneOf,
663
+ // Enum validators
664
+ isValidStatus,
665
+ isValidEmploymentType,
666
+ // Composite validators
667
+ composeValidators,
668
+ createValidator,
669
+ hasRequiredFields
670
+ };
671
+ function toObjectId(id) {
672
+ if (id instanceof Types.ObjectId) return id;
673
+ return new Types.ObjectId(id);
674
+ }
675
+ function safeToObjectId(id) {
676
+ if (id instanceof Types.ObjectId) return id;
677
+ if (typeof id === "string" && Types.ObjectId.isValid(id)) {
678
+ return new Types.ObjectId(id);
679
+ }
680
+ return null;
681
+ }
682
+ function isValidObjectId(value) {
683
+ if (value instanceof Types.ObjectId) return true;
684
+ if (typeof value === "string") return Types.ObjectId.isValid(value);
685
+ return false;
686
+ }
687
+ var QueryBuilder = class {
688
+ query;
689
+ constructor(initialQuery = {}) {
690
+ this.query = { ...initialQuery };
691
+ }
692
+ /**
693
+ * Add where condition
694
+ */
695
+ where(field, value) {
696
+ this.query[field] = value;
697
+ return this;
698
+ }
699
+ /**
700
+ * Add $in condition
701
+ */
702
+ whereIn(field, values) {
703
+ this.query[field] = { $in: values };
704
+ return this;
705
+ }
706
+ /**
707
+ * Add $nin condition
708
+ */
709
+ whereNotIn(field, values) {
710
+ this.query[field] = { $nin: values };
711
+ return this;
712
+ }
713
+ /**
714
+ * Add $gte condition
715
+ */
716
+ whereGte(field, value) {
717
+ const existing = this.query[field] || {};
718
+ this.query[field] = { ...existing, $gte: value };
719
+ return this;
720
+ }
721
+ /**
722
+ * Add $lte condition
723
+ */
724
+ whereLte(field, value) {
725
+ const existing = this.query[field] || {};
726
+ this.query[field] = { ...existing, $lte: value };
727
+ return this;
728
+ }
729
+ /**
730
+ * Add $gt condition
731
+ */
732
+ whereGt(field, value) {
733
+ const existing = this.query[field] || {};
734
+ this.query[field] = { ...existing, $gt: value };
735
+ return this;
736
+ }
737
+ /**
738
+ * Add $lt condition
739
+ */
740
+ whereLt(field, value) {
741
+ const existing = this.query[field] || {};
742
+ this.query[field] = { ...existing, $lt: value };
743
+ return this;
744
+ }
745
+ /**
746
+ * Add between condition
747
+ */
748
+ whereBetween(field, start, end) {
749
+ this.query[field] = { $gte: start, $lte: end };
750
+ return this;
751
+ }
752
+ /**
753
+ * Add $exists condition
754
+ */
755
+ whereExists(field) {
756
+ this.query[field] = { $exists: true };
757
+ return this;
758
+ }
759
+ /**
760
+ * Add $exists: false condition
761
+ */
762
+ whereNotExists(field) {
763
+ this.query[field] = { $exists: false };
764
+ return this;
765
+ }
766
+ /**
767
+ * Add $ne condition
768
+ */
769
+ whereNot(field, value) {
770
+ this.query[field] = { $ne: value };
771
+ return this;
772
+ }
773
+ /**
774
+ * Add regex condition
775
+ */
776
+ whereRegex(field, pattern, flags = "i") {
777
+ this.query[field] = { $regex: pattern, $options: flags };
778
+ return this;
779
+ }
780
+ /**
781
+ * Merge another query
782
+ */
783
+ merge(otherQuery) {
784
+ this.query = { ...this.query, ...otherQuery };
785
+ return this;
786
+ }
787
+ /**
788
+ * Build and return the query
789
+ */
790
+ build() {
791
+ return { ...this.query };
792
+ }
793
+ };
794
+ var EmployeeQueryBuilder = class extends QueryBuilder {
795
+ /**
796
+ * Filter by organization
797
+ */
798
+ forOrganization(organizationId) {
799
+ return this.where("organizationId", toObjectId(organizationId));
800
+ }
801
+ /**
802
+ * Filter by user
803
+ */
804
+ forUser(userId) {
805
+ return this.where("userId", toObjectId(userId));
806
+ }
807
+ /**
808
+ * Filter by status(es)
809
+ */
810
+ withStatus(...statuses) {
811
+ if (statuses.length === 1) {
812
+ return this.where("status", statuses[0]);
813
+ }
814
+ return this.whereIn("status", statuses);
815
+ }
816
+ /**
817
+ * Filter active employees
818
+ */
819
+ active() {
820
+ return this.withStatus("active");
821
+ }
822
+ /**
823
+ * Filter employed employees (not terminated)
824
+ */
825
+ employed() {
826
+ return this.whereIn("status", ["active", "on_leave", "suspended"]);
827
+ }
828
+ /**
829
+ * Filter terminated employees
830
+ */
831
+ terminated() {
832
+ return this.withStatus("terminated");
833
+ }
834
+ /**
835
+ * Filter by department
836
+ */
837
+ inDepartment(department) {
838
+ return this.where("department", department);
839
+ }
840
+ /**
841
+ * Filter by position
842
+ */
843
+ inPosition(position) {
844
+ return this.where("position", position);
845
+ }
846
+ /**
847
+ * Filter by employment type
848
+ */
849
+ withEmploymentType(type) {
850
+ return this.where("employmentType", type);
851
+ }
852
+ /**
853
+ * Filter by hire date (after)
854
+ */
855
+ hiredAfter(date) {
856
+ return this.whereGte("hireDate", date);
857
+ }
858
+ /**
859
+ * Filter by hire date (before)
860
+ */
861
+ hiredBefore(date) {
862
+ return this.whereLte("hireDate", date);
863
+ }
864
+ /**
865
+ * Filter by minimum salary
866
+ */
867
+ withMinSalary(amount) {
868
+ return this.whereGte("compensation.netSalary", amount);
869
+ }
870
+ /**
871
+ * Filter by maximum salary
872
+ */
873
+ withMaxSalary(amount) {
874
+ return this.whereLte("compensation.netSalary", amount);
875
+ }
876
+ /**
877
+ * Filter by salary range
878
+ */
879
+ withSalaryRange(min2, max2) {
880
+ return this.whereBetween("compensation.netSalary", min2, max2);
881
+ }
882
+ };
883
+ var PayrollQueryBuilder = class extends QueryBuilder {
884
+ /**
885
+ * Filter by organization
886
+ */
887
+ forOrganization(organizationId) {
888
+ return this.where("organizationId", toObjectId(organizationId));
889
+ }
890
+ /**
891
+ * Filter by employee
892
+ */
893
+ forEmployee(employeeId) {
894
+ return this.where("employeeId", toObjectId(employeeId));
895
+ }
896
+ /**
897
+ * Filter by period
898
+ */
899
+ forPeriod(month, year) {
900
+ if (month !== void 0) {
901
+ this.where("period.month", month);
902
+ }
903
+ if (year !== void 0) {
904
+ this.where("period.year", year);
905
+ }
906
+ return this;
907
+ }
908
+ /**
909
+ * Filter by status(es)
910
+ */
911
+ withStatus(...statuses) {
912
+ if (statuses.length === 1) {
913
+ return this.where("status", statuses[0]);
914
+ }
915
+ return this.whereIn("status", statuses);
916
+ }
917
+ /**
918
+ * Filter paid records
919
+ */
920
+ paid() {
921
+ return this.withStatus("paid");
922
+ }
923
+ /**
924
+ * Filter pending records
925
+ */
926
+ pending() {
927
+ return this.whereIn("status", ["pending", "processing"]);
928
+ }
929
+ /**
930
+ * Filter by date range
931
+ */
932
+ inDateRange(start, end) {
933
+ return this.whereBetween("period.payDate", start, end);
934
+ }
935
+ /**
936
+ * Filter exported records
937
+ */
938
+ exported() {
939
+ return this.where("exported", true);
940
+ }
941
+ /**
942
+ * Filter not exported records
943
+ */
944
+ notExported() {
945
+ return this.where("exported", false);
946
+ }
947
+ };
948
+ function employee() {
949
+ return new EmployeeQueryBuilder();
950
+ }
951
+ function payroll() {
952
+ return new PayrollQueryBuilder();
953
+ }
954
+ function createQueryBuilder(initialQuery) {
955
+ return new QueryBuilder(initialQuery);
956
+ }
957
+ function buildEmployeeQuery(options) {
958
+ const builder = employee().forOrganization(options.organizationId);
959
+ if (options.userId) {
960
+ builder.forUser(options.userId);
961
+ }
962
+ if (options.statuses) {
963
+ builder.withStatus(...options.statuses);
964
+ }
965
+ if (options.department) {
966
+ builder.inDepartment(options.department);
967
+ }
968
+ if (options.employmentType) {
969
+ builder.withEmploymentType(options.employmentType);
970
+ }
971
+ return builder.build();
972
+ }
973
+ function buildPayrollQuery(options) {
974
+ const builder = payroll();
975
+ if (options.organizationId) {
976
+ builder.forOrganization(options.organizationId);
977
+ }
978
+ if (options.employeeId) {
979
+ builder.forEmployee(options.employeeId);
980
+ }
981
+ if (options.month || options.year) {
982
+ builder.forPeriod(options.month, options.year);
983
+ }
984
+ if (options.statuses) {
985
+ builder.withStatus(...options.statuses);
986
+ }
987
+ return builder.build();
988
+ }
989
+ function buildAggregationPipeline(...stages) {
990
+ return stages.filter((stage) => !!stage);
991
+ }
992
+ function matchStage(query) {
993
+ return { $match: query };
994
+ }
995
+ function groupStage(groupBy, aggregations) {
996
+ return {
997
+ $group: {
998
+ _id: groupBy,
999
+ ...aggregations
1000
+ }
1001
+ };
1002
+ }
1003
+ function sortStage(sortBy) {
1004
+ return { $sort: sortBy };
1005
+ }
1006
+ function limitStage(limit) {
1007
+ return { $limit: limit };
1008
+ }
1009
+ function skipStage(skip) {
1010
+ return { $skip: skip };
1011
+ }
1012
+ function projectStage(fields) {
1013
+ return { $project: fields };
1014
+ }
1015
+ function lookupStage(options) {
1016
+ return { $lookup: options };
1017
+ }
1018
+ function unwindStage(path, options = {}) {
1019
+ return { $unwind: { path, ...options } };
1020
+ }
1021
+ var query_builders_default = {
1022
+ toObjectId,
1023
+ safeToObjectId,
1024
+ isValidObjectId,
1025
+ QueryBuilder,
1026
+ EmployeeQueryBuilder,
1027
+ PayrollQueryBuilder,
1028
+ employee,
1029
+ payroll,
1030
+ createQueryBuilder,
1031
+ buildEmployeeQuery,
1032
+ buildPayrollQuery,
1033
+ buildAggregationPipeline,
1034
+ matchStage,
1035
+ groupStage,
1036
+ sortStage,
1037
+ limitStage,
1038
+ skipStage,
1039
+ projectStage,
1040
+ lookupStage,
1041
+ unwindStage
1042
+ };
1043
+
1044
+ export { EmployeeQueryBuilder, PayrollQueryBuilder, QueryBuilder, addDays, addMonths, addYears, applyPercentage, applyProRating, applyTaxBrackets, buildAggregationPipeline, buildEmployeeQuery, buildPayrollQuery, calculateAllowanceAmount, calculateAllowances, calculateCompensationBreakdown, calculateDailyRate, calculateDeductionAmount, calculateDeductions, calculateGross, calculateHourlyRate, calculateNet, calculateOvertime, calculatePercentage, calculateProRatedSalary, calculateProRating, calculateProbationEnd, calculateTax, calculateTotalCompensation, calculateYearsOfService, calculation_default as calculationUtils, canReceiveSalary, canUpdateEmployment, compose, composeValidators, createAllowanceCalculator, createChildLogger, createDeductionCalculator, createQueryBuilder, createSilentLogger, createValidator, date_default as dateUtils, daysBetween, diffInDays, diffInMonths, diffInYears, disableLogging, employee, enableLogging, endOfDay, endOfMonth, endOfYear, formatDateForDB, formatPeriod, getCurrentPeriod, getDayName, getDayOfWeek, getDaysInMonth, getLogger, getMonthName, getPayPeriod, getPayPeriodDateRange, getShortMonthName, getWorkingDaysInMonth, groupStage, hasCompensation, hasCompletedProbation, hasRequiredFields, inRange, isActive, isDateInRange, isEligibleForBonus, isEligibleForPayroll, isEmployed, isInProbation, isInRange, isLoggingEnabled, isOnLeave, isOnProbation, isPositive, isSuspended, isTerminated, isValidBankDetails, isValidCompensation, isValidEmploymentType, isValidObjectId, isValidStatus, isWeekday, isWeekend, limitStage, logger, lookupStage, matchStage, max, maxValue, min, minValue, monthsBetween, oneOf, parseDBDate, parsePeriod, payroll, pipe, projectStage, query_builders_default as queryBuilders, required, resetLogger, roundTo, safeToObjectId, setLogger, skipStage, sortStage, startOfDay, startOfMonth, startOfYear, subDays, subMonths, sum, sumAllowances, sumBy, sumDeductions, toObjectId, unwindStage, validation_default as validationUtils };
1045
+ //# sourceMappingURL=index.js.map
1046
+ //# sourceMappingURL=index.js.map