@classytic/payroll 1.0.2 → 2.3.0

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

Potentially problematic release.


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

Files changed (78) hide show
  1. package/README.md +2599 -574
  2. package/dist/calculators/index.d.ts +433 -0
  3. package/dist/calculators/index.js +283 -0
  4. package/dist/calculators/index.js.map +1 -0
  5. package/dist/core/index.d.ts +314 -0
  6. package/dist/core/index.js +1166 -0
  7. package/dist/core/index.js.map +1 -0
  8. package/dist/employee-identity-DXhgOgXE.d.ts +473 -0
  9. package/dist/employee.factory-BlZqhiCk.d.ts +189 -0
  10. package/dist/idempotency-Cw2CWicb.d.ts +52 -0
  11. package/dist/index.d.ts +902 -0
  12. package/dist/index.js +9108 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/jurisdiction/index.d.ts +660 -0
  15. package/dist/jurisdiction/index.js +533 -0
  16. package/dist/jurisdiction/index.js.map +1 -0
  17. package/dist/payroll.d.ts +429 -0
  18. package/dist/payroll.js +5192 -0
  19. package/dist/payroll.js.map +1 -0
  20. package/dist/schemas/index.d.ts +3262 -0
  21. package/dist/schemas/index.js +780 -0
  22. package/dist/schemas/index.js.map +1 -0
  23. package/dist/services/index.d.ts +582 -0
  24. package/dist/services/index.js +2172 -0
  25. package/dist/services/index.js.map +1 -0
  26. package/dist/shift-compliance/index.d.ts +1171 -0
  27. package/dist/shift-compliance/index.js +1479 -0
  28. package/dist/shift-compliance/index.js.map +1 -0
  29. package/dist/types-BN3K_Uhr.d.ts +1842 -0
  30. package/dist/utils/index.d.ts +893 -0
  31. package/dist/utils/index.js +1515 -0
  32. package/dist/utils/index.js.map +1 -0
  33. package/package.json +72 -37
  34. package/dist/types/config.d.ts +0 -162
  35. package/dist/types/core/compensation.manager.d.ts +0 -54
  36. package/dist/types/core/employment.manager.d.ts +0 -49
  37. package/dist/types/core/payroll.manager.d.ts +0 -60
  38. package/dist/types/enums.d.ts +0 -117
  39. package/dist/types/factories/compensation.factory.d.ts +0 -196
  40. package/dist/types/factories/employee.factory.d.ts +0 -149
  41. package/dist/types/factories/payroll.factory.d.ts +0 -319
  42. package/dist/types/hrm.orchestrator.d.ts +0 -47
  43. package/dist/types/index.d.ts +0 -20
  44. package/dist/types/init.d.ts +0 -30
  45. package/dist/types/models/payroll-record.model.d.ts +0 -3
  46. package/dist/types/plugins/employee.plugin.d.ts +0 -2
  47. package/dist/types/schemas/employment.schema.d.ts +0 -959
  48. package/dist/types/services/compensation.service.d.ts +0 -94
  49. package/dist/types/services/employee.service.d.ts +0 -28
  50. package/dist/types/services/payroll.service.d.ts +0 -30
  51. package/dist/types/utils/calculation.utils.d.ts +0 -26
  52. package/dist/types/utils/date.utils.d.ts +0 -35
  53. package/dist/types/utils/logger.d.ts +0 -12
  54. package/dist/types/utils/query-builders.d.ts +0 -83
  55. package/dist/types/utils/validation.utils.d.ts +0 -33
  56. package/payroll.d.ts +0 -241
  57. package/src/config.js +0 -177
  58. package/src/core/compensation.manager.js +0 -242
  59. package/src/core/employment.manager.js +0 -224
  60. package/src/core/payroll.manager.js +0 -499
  61. package/src/enums.js +0 -141
  62. package/src/factories/compensation.factory.js +0 -198
  63. package/src/factories/employee.factory.js +0 -173
  64. package/src/factories/payroll.factory.js +0 -413
  65. package/src/hrm.orchestrator.js +0 -139
  66. package/src/index.js +0 -172
  67. package/src/init.js +0 -62
  68. package/src/models/payroll-record.model.js +0 -126
  69. package/src/plugins/employee.plugin.js +0 -164
  70. package/src/schemas/employment.schema.js +0 -126
  71. package/src/services/compensation.service.js +0 -231
  72. package/src/services/employee.service.js +0 -162
  73. package/src/services/payroll.service.js +0 -213
  74. package/src/utils/calculation.utils.js +0 -91
  75. package/src/utils/date.utils.js +0 -120
  76. package/src/utils/logger.js +0 -36
  77. package/src/utils/query-builders.js +0 -185
  78. package/src/utils/validation.utils.js +0 -122
@@ -0,0 +1,533 @@
1
+ // src/jurisdiction/registry.ts
2
+ var JurisdictionRegistry = class {
3
+ jurisdictions = /* @__PURE__ */ new Map();
4
+ /**
5
+ * Register a jurisdiction
6
+ */
7
+ register(jurisdiction) {
8
+ const key = this.makeKey(jurisdiction);
9
+ this.validate(jurisdiction);
10
+ this.jurisdictions.set(key, jurisdiction);
11
+ }
12
+ /**
13
+ * Register multiple jurisdictions
14
+ */
15
+ registerMany(jurisdictions) {
16
+ for (const jurisdiction of jurisdictions) {
17
+ this.register(jurisdiction);
18
+ }
19
+ }
20
+ /**
21
+ * Get jurisdiction by identifier
22
+ */
23
+ get(identifier) {
24
+ const key = this.makeKeyFromIdentifier(identifier);
25
+ return this.jurisdictions.get(key);
26
+ }
27
+ /**
28
+ * Get jurisdiction with fallback to parent
29
+ */
30
+ getWithFallback(identifier) {
31
+ let jurisdiction = this.get(identifier);
32
+ if (jurisdiction) return jurisdiction;
33
+ if (identifier.city) {
34
+ jurisdiction = this.get({
35
+ country: identifier.country,
36
+ state: identifier.state
37
+ });
38
+ if (jurisdiction) return jurisdiction;
39
+ }
40
+ if (identifier.state || identifier.city) {
41
+ jurisdiction = this.get({
42
+ country: identifier.country
43
+ });
44
+ if (jurisdiction) return jurisdiction;
45
+ }
46
+ return void 0;
47
+ }
48
+ /**
49
+ * Check if jurisdiction is registered
50
+ */
51
+ has(identifier) {
52
+ return this.get(identifier) !== void 0;
53
+ }
54
+ /**
55
+ * Get all jurisdictions for a country
56
+ */
57
+ getByCountry(countryCode) {
58
+ const results = [];
59
+ for (const jurisdiction of this.jurisdictions.values()) {
60
+ const key = this.makeKey(jurisdiction);
61
+ if (key.startsWith(`${countryCode}:`)) {
62
+ results.push(jurisdiction);
63
+ }
64
+ }
65
+ return results;
66
+ }
67
+ /**
68
+ * Get all registered jurisdictions
69
+ */
70
+ getAll() {
71
+ return Array.from(this.jurisdictions.values());
72
+ }
73
+ /**
74
+ * Remove a jurisdiction
75
+ */
76
+ unregister(identifier) {
77
+ const key = this.makeKeyFromIdentifier(identifier);
78
+ return this.jurisdictions.delete(key);
79
+ }
80
+ /**
81
+ * Clear all jurisdictions
82
+ */
83
+ clear() {
84
+ this.jurisdictions.clear();
85
+ }
86
+ /**
87
+ * Get registry size
88
+ */
89
+ size() {
90
+ return this.jurisdictions.size;
91
+ }
92
+ // ============================================================================
93
+ // Helper Methods
94
+ // ============================================================================
95
+ makeKey(jurisdiction) {
96
+ return this.makeKeyFromId(jurisdiction.id);
97
+ }
98
+ makeKeyFromId(id) {
99
+ return id.toUpperCase();
100
+ }
101
+ makeKeyFromIdentifier(identifier) {
102
+ const parts = [identifier.country.toUpperCase()];
103
+ if (identifier.state) {
104
+ parts.push(identifier.state.toUpperCase());
105
+ }
106
+ if (identifier.city) {
107
+ parts.push(identifier.city.toUpperCase());
108
+ }
109
+ if (identifier.custom) {
110
+ parts.push(identifier.custom.toUpperCase());
111
+ }
112
+ return parts.join(":");
113
+ }
114
+ validate(jurisdiction) {
115
+ if (!jurisdiction.id) {
116
+ throw new Error("Jurisdiction must have an id");
117
+ }
118
+ if (!jurisdiction.name) {
119
+ throw new Error("Jurisdiction must have a name");
120
+ }
121
+ if (!jurisdiction.currency) {
122
+ throw new Error("Jurisdiction must have a currency");
123
+ }
124
+ if (!jurisdiction.tax) {
125
+ throw new Error("Jurisdiction must have tax configuration");
126
+ }
127
+ if (!jurisdiction.tax.incomeTax || !Array.isArray(jurisdiction.tax.incomeTax)) {
128
+ throw new Error("Jurisdiction must have income tax brackets");
129
+ }
130
+ if (!jurisdiction.overtime) {
131
+ throw new Error("Jurisdiction must have overtime configuration");
132
+ }
133
+ if (!jurisdiction.leave) {
134
+ throw new Error("Jurisdiction must have leave entitlements");
135
+ }
136
+ if (!jurisdiction.wage) {
137
+ throw new Error("Jurisdiction must have wage configuration");
138
+ }
139
+ if (!jurisdiction.workingHours) {
140
+ throw new Error("Jurisdiction must have working hours configuration");
141
+ }
142
+ }
143
+ };
144
+ var jurisdictionRegistry = new JurisdictionRegistry();
145
+ function registerJurisdiction(jurisdiction) {
146
+ jurisdictionRegistry.register(jurisdiction);
147
+ }
148
+ function registerJurisdictions(jurisdictions) {
149
+ jurisdictionRegistry.registerMany(jurisdictions);
150
+ }
151
+ function getJurisdiction(identifier) {
152
+ return jurisdictionRegistry.getWithFallback(identifier);
153
+ }
154
+ function requireJurisdiction(identifier) {
155
+ const jurisdiction = getJurisdiction(identifier);
156
+ if (!jurisdiction) {
157
+ const key = jurisdictionRegistry["makeKeyFromIdentifier"](identifier);
158
+ throw new Error(`Jurisdiction not found: ${key}`);
159
+ }
160
+ return jurisdiction;
161
+ }
162
+ function hasJurisdiction(identifier) {
163
+ return jurisdictionRegistry.has(identifier);
164
+ }
165
+ function getJurisdictionsByCountry(countryCode) {
166
+ return jurisdictionRegistry.getByCountry(countryCode);
167
+ }
168
+
169
+ // src/jurisdiction/calculators/tax.ts
170
+ function calculateJurisdictionTax(input) {
171
+ const jurisdiction = requireJurisdiction(input.jurisdiction);
172
+ const config = jurisdiction.tax;
173
+ const taxableIncome = calculateTaxableIncome(
174
+ input.annualIncome,
175
+ config,
176
+ input.dependents,
177
+ input.customAllowances,
178
+ input.pensionContribution
179
+ );
180
+ const incomeTax = calculateIncomeTax(taxableIncome, config.incomeTax);
181
+ const { employeeAmount: socialSecurityEmployee, employerAmount: socialSecurityEmployer } = calculateSocialSecurity(input.annualIncome, config.socialSecurity);
182
+ const { employeeAmount: medicareEmployee, employerAmount: medicareEmployer } = calculateMedicare(
183
+ input.annualIncome,
184
+ config.medicare
185
+ );
186
+ const unemploymentEmployer = calculateUnemployment(input.annualIncome, config.unemployment);
187
+ const otherContributions = calculateOtherContributions(
188
+ input.annualIncome,
189
+ config.otherContributions || []
190
+ );
191
+ const totalEmployeeTax = incomeTax + socialSecurityEmployee + medicareEmployee + otherContributions.reduce((sum, c) => sum + c.employeeAmount, 0);
192
+ const totalEmployerTax = socialSecurityEmployer + medicareEmployer + unemploymentEmployer + otherContributions.reduce((sum, c) => sum + c.employerAmount, 0);
193
+ const effectiveRate = input.annualIncome > 0 ? totalEmployeeTax / input.annualIncome : 0;
194
+ return {
195
+ incomeTax,
196
+ socialSecurityEmployee,
197
+ socialSecurityEmployer,
198
+ medicareEmployee,
199
+ medicareEmployer,
200
+ unemploymentEmployer,
201
+ otherContributions,
202
+ totalEmployeeTax,
203
+ totalEmployerTax,
204
+ effectiveRate,
205
+ taxableIncome
206
+ };
207
+ }
208
+ function calculateTaxableIncome(grossIncome, config, dependents = 0, customAllowances = 0, pensionContribution = 0) {
209
+ let taxableIncome = grossIncome;
210
+ if (config.standardDeduction) {
211
+ taxableIncome -= config.standardDeduction;
212
+ }
213
+ if (config.allowances?.personal) {
214
+ taxableIncome -= config.allowances.personal;
215
+ }
216
+ if (config.allowances?.dependent && dependents > 0) {
217
+ taxableIncome -= config.allowances.dependent * dependents;
218
+ }
219
+ if (config.allowances?.pension && pensionContribution > 0) {
220
+ const pensionAllowance = Math.min(pensionContribution, config.allowances.pension);
221
+ taxableIncome -= pensionAllowance;
222
+ }
223
+ if (customAllowances > 0) {
224
+ taxableIncome -= customAllowances;
225
+ }
226
+ return Math.max(0, taxableIncome);
227
+ }
228
+ function calculateIncomeTax(taxableIncome, brackets) {
229
+ let tax = 0;
230
+ for (const bracket of brackets) {
231
+ if (taxableIncome <= bracket.min) {
232
+ continue;
233
+ }
234
+ const taxableInBracket = Math.min(taxableIncome, bracket.max) - bracket.min;
235
+ const bracketTax = taxableInBracket * bracket.rate;
236
+ tax += bracketTax + (bracket.fixedAmount || 0);
237
+ }
238
+ return Math.round(tax);
239
+ }
240
+ function calculateSocialSecurity(annualIncome, config) {
241
+ if (!config) {
242
+ return { employeeAmount: 0, employerAmount: 0 };
243
+ }
244
+ let taxableIncome = annualIncome;
245
+ if (config.floor && taxableIncome < config.floor) {
246
+ return { employeeAmount: 0, employerAmount: 0 };
247
+ }
248
+ if (config.ceiling && taxableIncome > config.ceiling) {
249
+ taxableIncome = config.ceiling;
250
+ }
251
+ const employeeAmount = Math.round(taxableIncome * config.employeeRate);
252
+ const employerAmount = Math.round(taxableIncome * config.employerRate);
253
+ return { employeeAmount, employerAmount };
254
+ }
255
+ function calculateMedicare(annualIncome, config) {
256
+ if (!config) {
257
+ return { employeeAmount: 0, employerAmount: 0 };
258
+ }
259
+ let employeeAmount = Math.round(annualIncome * config.employeeRate);
260
+ const employerAmount = Math.round(annualIncome * config.employerRate);
261
+ if (config.additionalRate && config.additionalThreshold) {
262
+ if (annualIncome > config.additionalThreshold) {
263
+ const additionalIncome = annualIncome - config.additionalThreshold;
264
+ employeeAmount += Math.round(additionalIncome * config.additionalRate);
265
+ }
266
+ }
267
+ return { employeeAmount, employerAmount };
268
+ }
269
+ function calculateUnemployment(annualIncome, config) {
270
+ if (!config) {
271
+ return 0;
272
+ }
273
+ let taxableIncome = annualIncome;
274
+ if (config.ceiling && taxableIncome > config.ceiling) {
275
+ taxableIncome = config.ceiling;
276
+ }
277
+ return Math.round(taxableIncome * config.employerRate);
278
+ }
279
+ function calculateOtherContributions(annualIncome, contributions) {
280
+ return contributions.map((contrib) => {
281
+ let taxableIncome = annualIncome;
282
+ if (contrib.ceiling && taxableIncome > contrib.ceiling) {
283
+ taxableIncome = contrib.ceiling;
284
+ }
285
+ const employeeAmount = contrib.employeeRate ? Math.round(taxableIncome * contrib.employeeRate) : 0;
286
+ const employerAmount = contrib.employerRate ? Math.round(taxableIncome * contrib.employerRate) : 0;
287
+ return {
288
+ name: contrib.name,
289
+ employeeAmount,
290
+ employerAmount
291
+ };
292
+ });
293
+ }
294
+ function calculateMonthlyTax(monthlyIncome, jurisdiction, options) {
295
+ const annualIncome = monthlyIncome * 12;
296
+ const result = calculateJurisdictionTax({
297
+ annualIncome,
298
+ jurisdiction,
299
+ dependents: options?.dependents,
300
+ customAllowances: options?.customAllowances ? options.customAllowances * 12 : void 0,
301
+ pensionContribution: options?.pensionContribution ? options.pensionContribution * 12 : void 0
302
+ });
303
+ return {
304
+ monthlyIncomeTax: Math.round(result.incomeTax / 12),
305
+ monthlySocialSecurity: Math.round(result.socialSecurityEmployee / 12),
306
+ monthlyMedicare: Math.round(result.medicareEmployee / 12),
307
+ monthlyTotal: Math.round(result.totalEmployeeTax / 12),
308
+ effectiveRate: result.effectiveRate
309
+ };
310
+ }
311
+ function compareTaxBurden(annualIncome, jurisdictions) {
312
+ return jurisdictions.map((jurisdiction) => {
313
+ const jurisdictionDef = requireJurisdiction(jurisdiction);
314
+ const result = calculateJurisdictionTax({
315
+ annualIncome,
316
+ jurisdiction
317
+ });
318
+ return {
319
+ jurisdiction,
320
+ jurisdictionName: jurisdictionDef.name,
321
+ result
322
+ };
323
+ });
324
+ }
325
+
326
+ // src/jurisdiction/calculators/compliance.ts
327
+ function checkCompliance(data, jurisdiction) {
328
+ const jurisdictionDef = requireJurisdiction(jurisdiction);
329
+ const violations = [];
330
+ violations.push(...checkMinimumWage(data, jurisdictionDef.wage.minimumWage.amount));
331
+ violations.push(
332
+ ...checkMaximumHours(data, jurisdictionDef.workingHours.maxDailyHours, jurisdictionDef.workingHours.maxWeeklyHours)
333
+ );
334
+ violations.push(...checkPayFrequency(data, jurisdictionDef.wage.payFrequency));
335
+ violations.push(...checkLeaveEntitlements(data, jurisdictionDef.leave));
336
+ for (const rule of jurisdictionDef.complianceRules) {
337
+ violations.push(...rule.validate(data));
338
+ }
339
+ return violations;
340
+ }
341
+ function checkBulkCompliance(employees, options) {
342
+ const results = employees.map((employee) => ({
343
+ employee,
344
+ violations: checkCompliance(employee, employee.jurisdiction)
345
+ }));
346
+ if (options?.severityFilter) {
347
+ results.forEach((result) => {
348
+ result.violations = result.violations.filter(
349
+ (v) => options.severityFilter.includes(v.severity)
350
+ );
351
+ });
352
+ }
353
+ if (options?.categoryFilter) {
354
+ results.forEach((result) => {
355
+ result.violations = result.violations.filter((v) => {
356
+ const rule = v.ruleId.split(":")[0];
357
+ return options.categoryFilter.includes(rule);
358
+ });
359
+ });
360
+ }
361
+ return results.filter((r) => r.violations.length > 0);
362
+ }
363
+ function checkMinimumWage(data, minimumWage) {
364
+ const violations = [];
365
+ const hoursPerMonth = 160;
366
+ const hourlyWage = data.baseSalary / hoursPerMonth;
367
+ if (hourlyWage < minimumWage) {
368
+ violations.push({
369
+ ruleId: "wage:minimum-wage",
370
+ ruleName: "Minimum Wage Violation",
371
+ severity: "critical",
372
+ message: `Hourly wage ${hourlyWage.toFixed(2)} is below minimum wage ${minimumWage.toFixed(2)}`,
373
+ remediation: `Increase base salary to at least ${(minimumWage * hoursPerMonth).toFixed(2)} per month`,
374
+ penalty: (minimumWage * hoursPerMonth - data.baseSalary) * 2
375
+ // Double damages
376
+ });
377
+ }
378
+ return violations;
379
+ }
380
+ function checkMaximumHours(data, maxDailyHours, maxWeeklyHours) {
381
+ const violations = [];
382
+ if (data.dailyHours && data.dailyHours > maxDailyHours) {
383
+ violations.push({
384
+ ruleId: "hours:max-daily",
385
+ ruleName: "Maximum Daily Hours Exceeded",
386
+ severity: "high",
387
+ message: `Employee worked ${data.dailyHours} hours, exceeding maximum of ${maxDailyHours} hours`,
388
+ remediation: "Reduce daily hours or obtain special exemption"
389
+ });
390
+ }
391
+ const weeklyHours = data.hoursWorked || 0;
392
+ if (weeklyHours > maxWeeklyHours) {
393
+ violations.push({
394
+ ruleId: "hours:max-weekly",
395
+ ruleName: "Maximum Weekly Hours Exceeded",
396
+ severity: "high",
397
+ message: `Employee worked ${weeklyHours} hours, exceeding maximum of ${maxWeeklyHours} hours`,
398
+ remediation: "Ensure proper overtime authorization and rest periods"
399
+ });
400
+ }
401
+ return violations;
402
+ }
403
+ function checkPayFrequency(data, config) {
404
+ const violations = [];
405
+ if (data.payFrequency && !config.allowed.includes(data.payFrequency)) {
406
+ violations.push({
407
+ ruleId: "wage:pay-frequency",
408
+ ruleName: "Invalid Pay Frequency",
409
+ severity: "medium",
410
+ message: `Pay frequency '${data.payFrequency}' is not allowed in this jurisdiction`,
411
+ remediation: `Use one of: ${config.allowed.join(", ")}`
412
+ });
413
+ }
414
+ return violations;
415
+ }
416
+ function checkLeaveEntitlements(data, config) {
417
+ const violations = [];
418
+ if (data.leaveBalance) {
419
+ if (data.leaveBalance.annual < 0) {
420
+ violations.push({
421
+ ruleId: "leave:negative-balance",
422
+ ruleName: "Negative Leave Balance",
423
+ severity: "medium",
424
+ message: "Employee has negative annual leave balance",
425
+ remediation: "Review leave usage and accrual calculations"
426
+ });
427
+ }
428
+ if (data.leaveBalance.sick < 0) {
429
+ violations.push({
430
+ ruleId: "leave:negative-sick-balance",
431
+ ruleName: "Negative Sick Leave Balance",
432
+ severity: "low",
433
+ message: "Employee has negative sick leave balance",
434
+ remediation: "Review sick leave policy and usage"
435
+ });
436
+ }
437
+ }
438
+ return violations;
439
+ }
440
+ function generateComplianceReport(employees, options) {
441
+ const results = checkBulkCompliance(employees);
442
+ const allViolations = results.flatMap((r) => r.violations);
443
+ const summary = {
444
+ totalEmployees: employees.length,
445
+ compliantEmployees: employees.length - results.length,
446
+ violationCount: allViolations.length,
447
+ criticalViolations: allViolations.filter((v) => v.severity === "critical").length,
448
+ highViolations: allViolations.filter((v) => v.severity === "high").length,
449
+ mediumViolations: allViolations.filter((v) => v.severity === "medium").length,
450
+ lowViolations: allViolations.filter((v) => v.severity === "low").length
451
+ };
452
+ const violations = results.map((r) => {
453
+ const jurisdictionKey = makeJurisdictionKey(r.employee.jurisdiction);
454
+ return {
455
+ employeeId: r.employee.id || "unknown",
456
+ employeeName: r.employee.name || "Unknown",
457
+ jurisdiction: jurisdictionKey,
458
+ violations: r.violations
459
+ };
460
+ });
461
+ let byJurisdiction;
462
+ if (options?.groupByJurisdiction) {
463
+ byJurisdiction = /* @__PURE__ */ new Map();
464
+ for (const employee of employees) {
465
+ const key = makeJurisdictionKey(employee.jurisdiction);
466
+ if (!byJurisdiction.has(key)) {
467
+ byJurisdiction.set(key, {
468
+ employeeCount: 0,
469
+ violationCount: 0,
470
+ violations: []
471
+ });
472
+ }
473
+ const group = byJurisdiction.get(key);
474
+ group.employeeCount++;
475
+ const employeeViolations = results.find((r) => r.employee === employee)?.violations || [];
476
+ group.violationCount += employeeViolations.length;
477
+ group.violations.push(...employeeViolations);
478
+ }
479
+ }
480
+ return {
481
+ summary,
482
+ violations,
483
+ byJurisdiction
484
+ };
485
+ }
486
+ function makeJurisdictionKey(identifier) {
487
+ const parts = [identifier.country];
488
+ if (identifier.state) parts.push(identifier.state);
489
+ if (identifier.city) parts.push(identifier.city);
490
+ return parts.join(":");
491
+ }
492
+
493
+ // src/jurisdiction/index.ts
494
+ function createJurisdictionDefinition(definition) {
495
+ return definition;
496
+ }
497
+ function extendJurisdiction(base, overrides) {
498
+ return {
499
+ ...base,
500
+ ...overrides,
501
+ level: overrides.level || "state",
502
+ parent: base.id,
503
+ tax: {
504
+ ...base.tax,
505
+ ...overrides.tax || {}
506
+ },
507
+ overtime: {
508
+ ...base.overtime,
509
+ ...overrides.overtime || {}
510
+ },
511
+ leave: {
512
+ ...base.leave,
513
+ ...overrides.leave || {}
514
+ },
515
+ wage: {
516
+ ...base.wage,
517
+ ...overrides.wage || {}
518
+ },
519
+ workingHours: {
520
+ ...base.workingHours,
521
+ ...overrides.workingHours || {}
522
+ },
523
+ complianceRules: overrides.complianceRules || base.complianceRules,
524
+ metadata: {
525
+ ...base.metadata,
526
+ ...overrides.metadata || {}
527
+ }
528
+ };
529
+ }
530
+
531
+ export { calculateJurisdictionTax, calculateMonthlyTax, checkBulkCompliance, checkCompliance, compareTaxBurden, createJurisdictionDefinition, extendJurisdiction, generateComplianceReport, getJurisdiction, getJurisdictionsByCountry, hasJurisdiction, jurisdictionRegistry, registerJurisdiction, registerJurisdictions, requireJurisdiction };
532
+ //# sourceMappingURL=index.js.map
533
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/jurisdiction/registry.ts","../../src/jurisdiction/calculators/tax.ts","../../src/jurisdiction/calculators/compliance.ts","../../src/jurisdiction/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @classytic/payroll - Jurisdiction Registry\n *\n * Pluggable jurisdiction system. Register custom jurisdictions at runtime.\n */\n\nimport type { JurisdictionDefinition, JurisdictionIdentifier } from './types.js';\n\n// ============================================================================\n// Registry\n// ============================================================================\n\nclass JurisdictionRegistry {\n private jurisdictions = new Map<string, JurisdictionDefinition>();\n\n /**\n * Register a jurisdiction\n */\n register(jurisdiction: JurisdictionDefinition): void {\n const key = this.makeKey(jurisdiction);\n\n // Validate jurisdiction\n this.validate(jurisdiction);\n\n this.jurisdictions.set(key, jurisdiction);\n }\n\n /**\n * Register multiple jurisdictions\n */\n registerMany(jurisdictions: JurisdictionDefinition[]): void {\n for (const jurisdiction of jurisdictions) {\n this.register(jurisdiction);\n }\n }\n\n /**\n * Get jurisdiction by identifier\n */\n get(identifier: JurisdictionIdentifier): JurisdictionDefinition | undefined {\n const key = this.makeKeyFromIdentifier(identifier);\n return this.jurisdictions.get(key);\n }\n\n /**\n * Get jurisdiction with fallback to parent\n */\n getWithFallback(identifier: JurisdictionIdentifier): JurisdictionDefinition | undefined {\n // Try exact match first\n let jurisdiction = this.get(identifier);\n if (jurisdiction) return jurisdiction;\n\n // Fall back to state level (if city was specified)\n if (identifier.city) {\n jurisdiction = this.get({\n country: identifier.country,\n state: identifier.state,\n });\n if (jurisdiction) return jurisdiction;\n }\n\n // Fall back to country level\n if (identifier.state || identifier.city) {\n jurisdiction = this.get({\n country: identifier.country,\n });\n if (jurisdiction) return jurisdiction;\n }\n\n return undefined;\n }\n\n /**\n * Check if jurisdiction is registered\n */\n has(identifier: JurisdictionIdentifier): boolean {\n return this.get(identifier) !== undefined;\n }\n\n /**\n * Get all jurisdictions for a country\n */\n getByCountry(countryCode: string): JurisdictionDefinition[] {\n const results: JurisdictionDefinition[] = [];\n\n for (const jurisdiction of this.jurisdictions.values()) {\n const key = this.makeKey(jurisdiction);\n if (key.startsWith(`${countryCode}:`)) {\n results.push(jurisdiction);\n }\n }\n\n return results;\n }\n\n /**\n * Get all registered jurisdictions\n */\n getAll(): JurisdictionDefinition[] {\n return Array.from(this.jurisdictions.values());\n }\n\n /**\n * Remove a jurisdiction\n */\n unregister(identifier: JurisdictionIdentifier): boolean {\n const key = this.makeKeyFromIdentifier(identifier);\n return this.jurisdictions.delete(key);\n }\n\n /**\n * Clear all jurisdictions\n */\n clear(): void {\n this.jurisdictions.clear();\n }\n\n /**\n * Get registry size\n */\n size(): number {\n return this.jurisdictions.size;\n }\n\n // ============================================================================\n // Helper Methods\n // ============================================================================\n\n private makeKey(jurisdiction: JurisdictionDefinition): string {\n return this.makeKeyFromId(jurisdiction.id);\n }\n\n private makeKeyFromId(id: string): string {\n return id.toUpperCase();\n }\n\n private makeKeyFromIdentifier(identifier: JurisdictionIdentifier): string {\n const parts = [identifier.country.toUpperCase()];\n\n if (identifier.state) {\n parts.push(identifier.state.toUpperCase());\n }\n\n if (identifier.city) {\n parts.push(identifier.city.toUpperCase());\n }\n\n if (identifier.custom) {\n parts.push(identifier.custom.toUpperCase());\n }\n\n return parts.join(':');\n }\n\n private validate(jurisdiction: JurisdictionDefinition): void {\n if (!jurisdiction.id) {\n throw new Error('Jurisdiction must have an id');\n }\n\n if (!jurisdiction.name) {\n throw new Error('Jurisdiction must have a name');\n }\n\n if (!jurisdiction.currency) {\n throw new Error('Jurisdiction must have a currency');\n }\n\n if (!jurisdiction.tax) {\n throw new Error('Jurisdiction must have tax configuration');\n }\n\n if (!jurisdiction.tax.incomeTax || !Array.isArray(jurisdiction.tax.incomeTax)) {\n throw new Error('Jurisdiction must have income tax brackets');\n }\n\n if (!jurisdiction.overtime) {\n throw new Error('Jurisdiction must have overtime configuration');\n }\n\n if (!jurisdiction.leave) {\n throw new Error('Jurisdiction must have leave entitlements');\n }\n\n if (!jurisdiction.wage) {\n throw new Error('Jurisdiction must have wage configuration');\n }\n\n if (!jurisdiction.workingHours) {\n throw new Error('Jurisdiction must have working hours configuration');\n }\n }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nexport const jurisdictionRegistry = new JurisdictionRegistry();\n\n// ============================================================================\n// Convenience Functions\n// ============================================================================\n\n/**\n * Register a jurisdiction\n */\nexport function registerJurisdiction(jurisdiction: JurisdictionDefinition): void {\n jurisdictionRegistry.register(jurisdiction);\n}\n\n/**\n * Register multiple jurisdictions\n */\nexport function registerJurisdictions(jurisdictions: JurisdictionDefinition[]): void {\n jurisdictionRegistry.registerMany(jurisdictions);\n}\n\n/**\n * Get jurisdiction\n */\nexport function getJurisdiction(identifier: JurisdictionIdentifier): JurisdictionDefinition | undefined {\n return jurisdictionRegistry.getWithFallback(identifier);\n}\n\n/**\n * Get jurisdiction (throws if not found)\n */\nexport function requireJurisdiction(identifier: JurisdictionIdentifier): JurisdictionDefinition {\n const jurisdiction = getJurisdiction(identifier);\n\n if (!jurisdiction) {\n const key = jurisdictionRegistry['makeKeyFromIdentifier'](identifier);\n throw new Error(`Jurisdiction not found: ${key}`);\n }\n\n return jurisdiction;\n}\n\n/**\n * Check if jurisdiction exists\n */\nexport function hasJurisdiction(identifier: JurisdictionIdentifier): boolean {\n return jurisdictionRegistry.has(identifier);\n}\n\n/**\n * Get all jurisdictions for a country\n */\nexport function getJurisdictionsByCountry(countryCode: string): JurisdictionDefinition[] {\n return jurisdictionRegistry.getByCountry(countryCode);\n}\n","/**\n * @classytic/payroll - Jurisdiction-Aware Tax Calculator\n *\n * Pure functions for calculating taxes using jurisdiction-specific rules.\n */\n\nimport type {\n JurisdictionIdentifier,\n TaxCalculationInput,\n TaxCalculationResult,\n TaxConfiguration,\n} from '../types.js';\nimport { requireJurisdiction } from '../registry.js';\n\n// ============================================================================\n// Tax Calculation\n// ============================================================================\n\n/**\n * Calculate comprehensive tax for an employee\n *\n * @example\n * ```typescript\n * const result = calculateJurisdictionTax({\n * annualIncome: 100000,\n * jurisdiction: { country: 'US', state: 'CA' },\n * dependents: 2,\n * });\n *\n * console.log(result.totalEmployeeTax); // Total tax burden\n * console.log(result.effectiveRate); // Effective tax rate\n * ```\n */\nexport function calculateJurisdictionTax(input: TaxCalculationInput): TaxCalculationResult {\n const jurisdiction = requireJurisdiction(input.jurisdiction);\n const config = jurisdiction.tax;\n\n // 1. Calculate taxable income (after allowances/deductions)\n const taxableIncome = calculateTaxableIncome(\n input.annualIncome,\n config,\n input.dependents,\n input.customAllowances,\n input.pensionContribution\n );\n\n // 2. Calculate income tax\n const incomeTax = calculateIncomeTax(taxableIncome, config.incomeTax);\n\n // 3. Calculate social security\n const { employeeAmount: socialSecurityEmployee, employerAmount: socialSecurityEmployer } =\n calculateSocialSecurity(input.annualIncome, config.socialSecurity);\n\n // 4. Calculate medicare\n const { employeeAmount: medicareEmployee, employerAmount: medicareEmployer } = calculateMedicare(\n input.annualIncome,\n config.medicare\n );\n\n // 5. Calculate unemployment\n const unemploymentEmployer = calculateUnemployment(input.annualIncome, config.unemployment);\n\n // 6. Calculate other contributions\n const otherContributions = calculateOtherContributions(\n input.annualIncome,\n config.otherContributions || []\n );\n\n // 7. Calculate totals\n const totalEmployeeTax =\n incomeTax +\n socialSecurityEmployee +\n medicareEmployee +\n otherContributions.reduce((sum, c) => sum + c.employeeAmount, 0);\n\n const totalEmployerTax =\n socialSecurityEmployer +\n medicareEmployer +\n unemploymentEmployer +\n otherContributions.reduce((sum, c) => sum + c.employerAmount, 0);\n\n const effectiveRate = input.annualIncome > 0 ? totalEmployeeTax / input.annualIncome : 0;\n\n return {\n incomeTax,\n socialSecurityEmployee,\n socialSecurityEmployer,\n medicareEmployee,\n medicareEmployer,\n unemploymentEmployer,\n otherContributions,\n totalEmployeeTax,\n totalEmployerTax,\n effectiveRate,\n taxableIncome,\n };\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Calculate taxable income after allowances and deductions\n */\nfunction calculateTaxableIncome(\n grossIncome: number,\n config: TaxConfiguration,\n dependents = 0,\n customAllowances = 0,\n pensionContribution = 0\n): number {\n let taxableIncome = grossIncome;\n\n // Apply standard deduction\n if (config.standardDeduction) {\n taxableIncome -= config.standardDeduction;\n }\n\n // Apply personal allowance\n if (config.allowances?.personal) {\n taxableIncome -= config.allowances.personal;\n }\n\n // Apply dependent allowance\n if (config.allowances?.dependent && dependents > 0) {\n taxableIncome -= config.allowances.dependent * dependents;\n }\n\n // Apply pension allowance\n if (config.allowances?.pension && pensionContribution > 0) {\n const pensionAllowance = Math.min(pensionContribution, config.allowances.pension);\n taxableIncome -= pensionAllowance;\n }\n\n // Apply custom allowances\n if (customAllowances > 0) {\n taxableIncome -= customAllowances;\n }\n\n return Math.max(0, taxableIncome);\n}\n\n/**\n * Calculate income tax using progressive brackets\n */\nfunction calculateIncomeTax(\n taxableIncome: number,\n brackets: TaxConfiguration['incomeTax']\n): number {\n let tax = 0;\n\n for (const bracket of brackets) {\n if (taxableIncome <= bracket.min) {\n continue;\n }\n\n const taxableInBracket = Math.min(taxableIncome, bracket.max) - bracket.min;\n const bracketTax = taxableInBracket * bracket.rate;\n\n // Add fixed amount if specified\n tax += bracketTax + (bracket.fixedAmount || 0);\n }\n\n return Math.round(tax);\n}\n\n/**\n * Calculate social security contributions\n */\nfunction calculateSocialSecurity(\n annualIncome: number,\n config?: TaxConfiguration['socialSecurity']\n): { employeeAmount: number; employerAmount: number } {\n if (!config) {\n return { employeeAmount: 0, employerAmount: 0 };\n }\n\n // Apply floor and ceiling\n let taxableIncome = annualIncome;\n\n if (config.floor && taxableIncome < config.floor) {\n return { employeeAmount: 0, employerAmount: 0 };\n }\n\n if (config.ceiling && taxableIncome > config.ceiling) {\n taxableIncome = config.ceiling;\n }\n\n const employeeAmount = Math.round(taxableIncome * config.employeeRate);\n const employerAmount = Math.round(taxableIncome * config.employerRate);\n\n return { employeeAmount, employerAmount };\n}\n\n/**\n * Calculate medicare contributions\n */\nfunction calculateMedicare(\n annualIncome: number,\n config?: TaxConfiguration['medicare']\n): { employeeAmount: number; employerAmount: number } {\n if (!config) {\n return { employeeAmount: 0, employerAmount: 0 };\n }\n\n let employeeAmount = Math.round(annualIncome * config.employeeRate);\n const employerAmount = Math.round(annualIncome * config.employerRate);\n\n // Additional medicare tax for high earners\n if (config.additionalRate && config.additionalThreshold) {\n if (annualIncome > config.additionalThreshold) {\n const additionalIncome = annualIncome - config.additionalThreshold;\n employeeAmount += Math.round(additionalIncome * config.additionalRate);\n }\n }\n\n return { employeeAmount, employerAmount };\n}\n\n/**\n * Calculate unemployment insurance\n */\nfunction calculateUnemployment(\n annualIncome: number,\n config?: TaxConfiguration['unemployment']\n): number {\n if (!config) {\n return 0;\n }\n\n let taxableIncome = annualIncome;\n\n if (config.ceiling && taxableIncome > config.ceiling) {\n taxableIncome = config.ceiling;\n }\n\n return Math.round(taxableIncome * config.employerRate);\n}\n\n/**\n * Calculate other mandatory contributions\n */\nfunction calculateOtherContributions(\n annualIncome: number,\n contributions: NonNullable<TaxConfiguration['otherContributions']>\n): Array<{ name: string; employeeAmount: number; employerAmount: number }> {\n return contributions.map((contrib) => {\n let taxableIncome = annualIncome;\n\n if (contrib.ceiling && taxableIncome > contrib.ceiling) {\n taxableIncome = contrib.ceiling;\n }\n\n const employeeAmount = contrib.employeeRate\n ? Math.round(taxableIncome * contrib.employeeRate)\n : 0;\n\n const employerAmount = contrib.employerRate\n ? Math.round(taxableIncome * contrib.employerRate)\n : 0;\n\n return {\n name: contrib.name,\n employeeAmount,\n employerAmount,\n };\n });\n}\n\n// ============================================================================\n// Monthly Tax Calculation (Convenience)\n// ============================================================================\n\n/**\n * Calculate monthly tax (convenience wrapper)\n */\nexport function calculateMonthlyTax(\n monthlyIncome: number,\n jurisdiction: JurisdictionIdentifier,\n options?: {\n dependents?: number;\n customAllowances?: number;\n pensionContribution?: number;\n }\n): {\n monthlyIncomeTax: number;\n monthlySocialSecurity: number;\n monthlyMedicare: number;\n monthlyTotal: number;\n effectiveRate: number;\n} {\n const annualIncome = monthlyIncome * 12;\n\n const result = calculateJurisdictionTax({\n annualIncome,\n jurisdiction,\n dependents: options?.dependents,\n customAllowances: options?.customAllowances ? options.customAllowances * 12 : undefined,\n pensionContribution: options?.pensionContribution\n ? options.pensionContribution * 12\n : undefined,\n });\n\n return {\n monthlyIncomeTax: Math.round(result.incomeTax / 12),\n monthlySocialSecurity: Math.round(result.socialSecurityEmployee / 12),\n monthlyMedicare: Math.round(result.medicareEmployee / 12),\n monthlyTotal: Math.round(result.totalEmployeeTax / 12),\n effectiveRate: result.effectiveRate,\n };\n}\n\n// ============================================================================\n// Tax Comparison (Multi-Jurisdiction)\n// ============================================================================\n\n/**\n * Compare tax burden across multiple jurisdictions\n */\nexport function compareTaxBurden(\n annualIncome: number,\n jurisdictions: JurisdictionIdentifier[]\n): Array<{\n jurisdiction: JurisdictionIdentifier;\n jurisdictionName: string;\n result: TaxCalculationResult;\n}> {\n return jurisdictions.map((jurisdiction) => {\n const jurisdictionDef = requireJurisdiction(jurisdiction);\n const result = calculateJurisdictionTax({\n annualIncome,\n jurisdiction,\n });\n\n return {\n jurisdiction,\n jurisdictionName: jurisdictionDef.name,\n result,\n };\n });\n}\n","/**\n * @classytic/payroll - Labor Law Compliance Checker\n *\n * Validates employment data against jurisdiction-specific labor laws.\n */\n\nimport type {\n JurisdictionIdentifier,\n ComplianceViolation,\n EmploymentData,\n} from '../types.js';\nimport { requireJurisdiction } from '../registry.js';\n\n// ============================================================================\n// Compliance Checking\n// ============================================================================\n\n/**\n * Check compliance for an employee\n *\n * @example\n * ```typescript\n * const violations = checkCompliance({\n * baseSalary: 2500,\n * currency: 'USD',\n * hoursWorked: 45,\n * jurisdiction: { country: 'US', state: 'CA' },\n * });\n *\n * if (violations.length > 0) {\n * console.log('Compliance issues found:', violations);\n * }\n * ```\n */\nexport function checkCompliance(\n data: EmploymentData,\n jurisdiction: JurisdictionIdentifier\n): ComplianceViolation[] {\n const jurisdictionDef = requireJurisdiction(jurisdiction);\n const violations: ComplianceViolation[] = [];\n\n // 1. Check minimum wage\n violations.push(...checkMinimumWage(data, jurisdictionDef.wage.minimumWage.amount));\n\n // 2. Check maximum hours\n violations.push(\n ...checkMaximumHours(data, jurisdictionDef.workingHours.maxDailyHours, jurisdictionDef.workingHours.maxWeeklyHours)\n );\n\n // 3. Check pay frequency\n violations.push(...checkPayFrequency(data, jurisdictionDef.wage.payFrequency));\n\n // 4. Check leave entitlements\n violations.push(...checkLeaveEntitlements(data, jurisdictionDef.leave));\n\n // 5. Run custom jurisdiction rules\n for (const rule of jurisdictionDef.complianceRules) {\n violations.push(...rule.validate(data));\n }\n\n return violations;\n}\n\n/**\n * Check multiple employees for compliance\n */\nexport function checkBulkCompliance(\n employees: Array<EmploymentData & { jurisdiction: JurisdictionIdentifier }>,\n options?: {\n severityFilter?: ComplianceViolation['severity'][];\n categoryFilter?: string[];\n }\n): Array<{\n employee: EmploymentData;\n violations: ComplianceViolation[];\n}> {\n const results = employees.map((employee) => ({\n employee,\n violations: checkCompliance(employee, employee.jurisdiction),\n }));\n\n // Filter by severity\n if (options?.severityFilter) {\n results.forEach((result) => {\n result.violations = result.violations.filter((v) =>\n options.severityFilter!.includes(v.severity)\n );\n });\n }\n\n // Filter by category\n if (options?.categoryFilter) {\n results.forEach((result) => {\n result.violations = result.violations.filter((v) => {\n const rule = v.ruleId.split(':')[0];\n return options.categoryFilter!.includes(rule);\n });\n });\n }\n\n return results.filter((r) => r.violations.length > 0);\n}\n\n// ============================================================================\n// Specific Compliance Checks\n// ============================================================================\n\n/**\n * Check if salary meets minimum wage\n */\nfunction checkMinimumWage(data: EmploymentData, minimumWage: number): ComplianceViolation[] {\n const violations: ComplianceViolation[] = [];\n\n // Calculate hourly wage\n const hoursPerMonth = 160; // Approximate (40 hours/week * 4 weeks)\n const hourlyWage = data.baseSalary / hoursPerMonth;\n\n if (hourlyWage < minimumWage) {\n violations.push({\n ruleId: 'wage:minimum-wage',\n ruleName: 'Minimum Wage Violation',\n severity: 'critical',\n message: `Hourly wage ${hourlyWage.toFixed(2)} is below minimum wage ${minimumWage.toFixed(2)}`,\n remediation: `Increase base salary to at least ${(minimumWage * hoursPerMonth).toFixed(2)} per month`,\n penalty: (minimumWage * hoursPerMonth - data.baseSalary) * 2, // Double damages\n });\n }\n\n return violations;\n}\n\n/**\n * Check maximum working hours\n */\nfunction checkMaximumHours(\n data: EmploymentData,\n maxDailyHours: number,\n maxWeeklyHours: number\n): ComplianceViolation[] {\n const violations: ComplianceViolation[] = [];\n\n // Daily hours check (if data available)\n if (data.dailyHours && data.dailyHours > maxDailyHours) {\n violations.push({\n ruleId: 'hours:max-daily',\n ruleName: 'Maximum Daily Hours Exceeded',\n severity: 'high',\n message: `Employee worked ${data.dailyHours} hours, exceeding maximum of ${maxDailyHours} hours`,\n remediation: 'Reduce daily hours or obtain special exemption',\n });\n }\n\n // Weekly hours check\n const weeklyHours = data.hoursWorked || 0;\n if (weeklyHours > maxWeeklyHours) {\n violations.push({\n ruleId: 'hours:max-weekly',\n ruleName: 'Maximum Weekly Hours Exceeded',\n severity: 'high',\n message: `Employee worked ${weeklyHours} hours, exceeding maximum of ${maxWeeklyHours} hours`,\n remediation: 'Ensure proper overtime authorization and rest periods',\n });\n }\n\n return violations;\n}\n\n/**\n * Check pay frequency compliance\n */\nfunction checkPayFrequency(\n data: EmploymentData,\n config: { allowed: string[]; default: string }\n): ComplianceViolation[] {\n const violations: ComplianceViolation[] = [];\n\n if (data.payFrequency && !config.allowed.includes(data.payFrequency)) {\n violations.push({\n ruleId: 'wage:pay-frequency',\n ruleName: 'Invalid Pay Frequency',\n severity: 'medium',\n message: `Pay frequency '${data.payFrequency}' is not allowed in this jurisdiction`,\n remediation: `Use one of: ${config.allowed.join(', ')}`,\n });\n }\n\n return violations;\n}\n\n/**\n * Check leave entitlements\n */\nfunction checkLeaveEntitlements(data: EmploymentData, config: any): ComplianceViolation[] {\n const violations: ComplianceViolation[] = [];\n\n // Check if leave balance is negative (shouldn't happen)\n if (data.leaveBalance) {\n if (data.leaveBalance.annual < 0) {\n violations.push({\n ruleId: 'leave:negative-balance',\n ruleName: 'Negative Leave Balance',\n severity: 'medium',\n message: 'Employee has negative annual leave balance',\n remediation: 'Review leave usage and accrual calculations',\n });\n }\n\n if (data.leaveBalance.sick < 0) {\n violations.push({\n ruleId: 'leave:negative-sick-balance',\n ruleName: 'Negative Sick Leave Balance',\n severity: 'low',\n message: 'Employee has negative sick leave balance',\n remediation: 'Review sick leave policy and usage',\n });\n }\n }\n\n return violations;\n}\n\n// ============================================================================\n// Compliance Reports\n// ============================================================================\n\n/**\n * Generate compliance report for an organization\n */\nexport function generateComplianceReport(\n employees: Array<EmploymentData & { jurisdiction: JurisdictionIdentifier; id: string; name: string }>,\n options?: {\n includeCompliant?: boolean;\n groupByJurisdiction?: boolean;\n }\n): {\n summary: {\n totalEmployees: number;\n compliantEmployees: number;\n violationCount: number;\n criticalViolations: number;\n highViolations: number;\n mediumViolations: number;\n lowViolations: number;\n };\n violations: Array<{\n employeeId: string;\n employeeName: string;\n jurisdiction: string;\n violations: ComplianceViolation[];\n }>;\n byJurisdiction?: Map<\n string,\n {\n employeeCount: number;\n violationCount: number;\n violations: ComplianceViolation[];\n }\n >;\n} {\n const results = checkBulkCompliance(employees);\n\n // Calculate summary\n const allViolations = results.flatMap((r) => r.violations);\n const summary = {\n totalEmployees: employees.length,\n compliantEmployees: employees.length - results.length,\n violationCount: allViolations.length,\n criticalViolations: allViolations.filter((v) => v.severity === 'critical').length,\n highViolations: allViolations.filter((v) => v.severity === 'high').length,\n mediumViolations: allViolations.filter((v) => v.severity === 'medium').length,\n lowViolations: allViolations.filter((v) => v.severity === 'low').length,\n };\n\n // Format violations\n const violations = results.map((r) => {\n const jurisdictionKey = makeJurisdictionKey(r.employee.jurisdiction);\n return {\n employeeId: r.employee.id || 'unknown',\n employeeName: r.employee.name || 'Unknown',\n jurisdiction: jurisdictionKey,\n violations: r.violations,\n };\n });\n\n // Group by jurisdiction if requested\n let byJurisdiction: Map<\n string,\n {\n employeeCount: number;\n violationCount: number;\n violations: ComplianceViolation[];\n }\n > | undefined;\n\n if (options?.groupByJurisdiction) {\n byJurisdiction = new Map();\n\n for (const employee of employees) {\n const key = makeJurisdictionKey(employee.jurisdiction);\n if (!byJurisdiction.has(key)) {\n byJurisdiction.set(key, {\n employeeCount: 0,\n violationCount: 0,\n violations: [],\n });\n }\n\n const group = byJurisdiction.get(key)!;\n group.employeeCount++;\n\n const employeeViolations = results.find((r) => r.employee === employee)?.violations || [];\n group.violationCount += employeeViolations.length;\n group.violations.push(...employeeViolations);\n }\n }\n\n return {\n summary,\n violations,\n byJurisdiction,\n };\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction makeJurisdictionKey(identifier: JurisdictionIdentifier): string {\n const parts = [identifier.country];\n if (identifier.state) parts.push(identifier.state);\n if (identifier.city) parts.push(identifier.city);\n return parts.join(':');\n}\n","/**\n * @classytic/payroll - Multi-Jurisdiction Support\n *\n * PURE TOOL - NO DEFAULTS\n *\n * This package provides the TOOLS for multi-jurisdiction payroll.\n * YOU provide the data (tax brackets, labor laws, etc.).\n *\n * WHY NO DEFAULTS?\n * - Tax laws change frequently (your app can update faster than package releases)\n * - Legal liability (you verify accuracy, not us)\n * - Minimal package (no unused data shipped to users)\n * - Flexibility (you own your compliance data)\n *\n * USAGE:\n * ```typescript\n * import { registerJurisdiction, calculateJurisdictionTax } from '@classytic/payroll/jurisdiction';\n *\n * // YOU define your jurisdiction data\n * const myCountry: JurisdictionDefinition = {\n * id: 'US',\n * name: 'United States',\n * currency: 'USD',\n * tax: { ... }, // Your research\n * overtime: { ... },\n * leave: { ... },\n * // ... etc\n * };\n *\n * // Register it\n * registerJurisdiction(myCountry);\n *\n * // Use it\n * const tax = calculateJurisdictionTax({\n * annualIncome: 100000,\n * jurisdiction: { country: 'US' },\n * });\n * ```\n *\n * SEE EXAMPLES:\n * - examples/jurisdiction-data/ for reference implementations\n * - These are EXAMPLES ONLY, not legal advice\n * - YOU are responsible for accuracy and compliance\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type {\n JurisdictionLevel,\n JurisdictionIdentifier,\n JurisdictionDefinition,\n TaxBracket,\n TaxConfiguration,\n TaxCalculationInput,\n TaxCalculationResult,\n OvertimeRule,\n OvertimeConfiguration,\n OvertimeCalculationBasis,\n LeaveEntitlement,\n ComplianceRule,\n ComplianceViolation,\n EmploymentData,\n WageConfiguration,\n WorkingHoursConfiguration,\n PaySlipData,\n PaySlipTemplate,\n StatutoryFilingRequirement,\n FilingCalendar,\n} from './types.js';\n\n// ============================================================================\n// Registry (Pure Tool)\n// ============================================================================\n\nexport {\n jurisdictionRegistry,\n registerJurisdiction,\n registerJurisdictions,\n getJurisdiction,\n requireJurisdiction,\n hasJurisdiction,\n getJurisdictionsByCountry,\n} from './registry.js';\n\n// ============================================================================\n// Calculators (Pure Functions)\n// ============================================================================\n\nexport {\n calculateJurisdictionTax,\n calculateMonthlyTax,\n compareTaxBurden,\n} from './calculators/tax.js';\n\nexport {\n checkCompliance,\n checkBulkCompliance,\n generateComplianceReport,\n} from './calculators/compliance.js';\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Create a jurisdiction definition with type safety\n *\n * @example\n * ```typescript\n * const myJurisdiction = createJurisdictionDefinition({\n * id: 'US',\n * name: 'United States',\n * level: 'country',\n * currency: 'USD',\n * locale: 'en-US',\n * effectiveFrom: new Date('2024-01-01'),\n * tax: { ... },\n * overtime: { ... },\n * leave: { ... },\n * wage: { ... },\n * workingHours: { ... },\n * complianceRules: [],\n * });\n *\n * registerJurisdiction(myJurisdiction);\n * ```\n */\nexport function createJurisdictionDefinition(\n definition: import('./types.js').JurisdictionDefinition\n): import('./types.js').JurisdictionDefinition {\n return definition;\n}\n\n/**\n * Helper to extend an existing jurisdiction (e.g., create a state from a country)\n *\n * @example\n * ```typescript\n * import { extendJurisdiction } from '@classytic/payroll/jurisdiction';\n *\n * // First get your base country jurisdiction (from your data)\n * const usFederal = getJurisdiction({ country: 'US' });\n *\n * // Extend it for a state\n * const california = extendJurisdiction(usFederal!, {\n * id: 'US:CA',\n * name: 'California',\n * parent: 'US',\n * level: 'state',\n * wage: {\n * minimumWage: { amount: 16, effectiveDate: new Date('2024-01-01') },\n * },\n * });\n *\n * registerJurisdiction(california);\n * ```\n */\nexport function extendJurisdiction(\n base: import('./types.js').JurisdictionDefinition,\n overrides: Partial<import('./types.js').JurisdictionDefinition> & {\n id: string;\n name: string;\n }\n): import('./types.js').JurisdictionDefinition {\n return {\n ...base,\n ...overrides,\n level: overrides.level || 'state',\n parent: base.id,\n tax: {\n ...base.tax,\n ...(overrides.tax || {}),\n } as any,\n overtime: {\n ...base.overtime,\n ...(overrides.overtime || {}),\n } as any,\n leave: {\n ...base.leave,\n ...(overrides.leave || {}),\n } as any,\n wage: {\n ...base.wage,\n ...(overrides.wage || {}),\n } as any,\n workingHours: {\n ...base.workingHours,\n ...(overrides.workingHours || {}),\n } as any,\n complianceRules: overrides.complianceRules || base.complianceRules,\n metadata: {\n ...base.metadata,\n ...(overrides.metadata || {}),\n } as any,\n };\n}\n"]}