payrolla-mcp 0.2.4 → 0.2.6
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.
- package/README.md +7 -3
- package/dist/index.js +167 -47
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -55,15 +55,19 @@ Calculate payroll for a single employee.
|
|
|
55
55
|
- `month` - Starting month (1-12)
|
|
56
56
|
- `periodCount` - Number of months (optional, default: 1)
|
|
57
57
|
- `ssiType` - SSI type: 'S4A', 'S4B', or 'S4C' (optional, default: 'S4A')
|
|
58
|
-
- `extraPayments` - Array of extra payments (optional)
|
|
58
|
+
- `extraPayments` - Array of extra payments (optional, supports `paymentType` = RegularPayment/Overtime/SocialAid/ExtraPay)
|
|
59
59
|
- `customParams` - Custom global parameters (optional)
|
|
60
|
+
- `cumulativeIncomeTaxBase` - Starting income tax base to carry over
|
|
61
|
+
- `cumulativeMinWageIncomeTaxBase` - Starting minimum wage income tax base to carry over
|
|
62
|
+
- `transferredSSIBase1` - Starting transferred SSI base 1
|
|
63
|
+
- `transferredSSIBase2` - Starting transferred SSI base 2
|
|
60
64
|
|
|
61
65
|
### calculate_bulk_payroll
|
|
62
66
|
|
|
63
67
|
Calculate payroll for multiple employees with shared parameters.
|
|
64
68
|
|
|
65
69
|
**Input:**
|
|
66
|
-
- `employees` - Array of employee objects
|
|
70
|
+
- `employees` - Array of employee objects (each can include extra payments with `paymentType` and starting cumulative/transfer bases)
|
|
67
71
|
- `year` - Calculation year
|
|
68
72
|
- `month` - Starting month
|
|
69
73
|
- `periodCount` - Number of months (use 12 for yearly)
|
|
@@ -120,4 +124,4 @@ Plan yearly payroll considering potential changes.
|
|
|
120
124
|
|
|
121
125
|
```
|
|
122
126
|
User: I have 3 employees: Ali 35k net, Ayse 45k net, Mehmet 60k gross.
|
|
123
|
-
What's my yearly budget if I give 10% raise and minimum wage becomes 30k?
|
|
127
|
+
What's my yearly budget if I give 10% raise and minimum wage becomes 30k?
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,23 @@ function mapSSIType(ssiType) {
|
|
|
30
30
|
function mapCalculationType(calcType) {
|
|
31
31
|
return calcType === "Gross" ? CalculationType.Gross : CalculationType.Net;
|
|
32
32
|
}
|
|
33
|
+
function mapPaymentType(paymentType) {
|
|
34
|
+
switch (paymentType) {
|
|
35
|
+
case 1:
|
|
36
|
+
case "RegularPayment":
|
|
37
|
+
return PaymentType.RegularPayment;
|
|
38
|
+
case 2:
|
|
39
|
+
case "Overtime":
|
|
40
|
+
return PaymentType.Overtime;
|
|
41
|
+
case 3:
|
|
42
|
+
case "SocialAid":
|
|
43
|
+
return PaymentType.SocialAid;
|
|
44
|
+
case 4:
|
|
45
|
+
case "ExtraPay":
|
|
46
|
+
default:
|
|
47
|
+
return PaymentType.ExtraPay;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
33
50
|
function buildCustomGlobalParams(customParams) {
|
|
34
51
|
if (!customParams) return void 0;
|
|
35
52
|
return {
|
|
@@ -50,7 +67,11 @@ async function calculatePayroll(client, input) {
|
|
|
50
67
|
month,
|
|
51
68
|
periodCount = 1,
|
|
52
69
|
extraPayments,
|
|
53
|
-
customParams
|
|
70
|
+
customParams,
|
|
71
|
+
cumulativeIncomeTaxBase = 0,
|
|
72
|
+
cumulativeMinWageIncomeTaxBase = 0,
|
|
73
|
+
transferredSSIBase1 = 0,
|
|
74
|
+
transferredSSIBase2 = 0
|
|
54
75
|
} = input;
|
|
55
76
|
const payments = [
|
|
56
77
|
{
|
|
@@ -66,21 +87,17 @@ async function calculatePayroll(client, input) {
|
|
|
66
87
|
payments.push({
|
|
67
88
|
paymentAmount: extra.amount,
|
|
68
89
|
paymentName: extra.name,
|
|
69
|
-
paymentType:
|
|
90
|
+
paymentType: mapPaymentType(extra.paymentType),
|
|
70
91
|
paymentRef: `extra_${i + 2}`,
|
|
71
92
|
calculationType: extra.type === "Net" ? CalculationType.Net : CalculationType.Gross
|
|
72
93
|
});
|
|
73
94
|
}
|
|
74
95
|
}
|
|
75
|
-
const
|
|
76
|
-
calcDate: `${year}-${String(month).padStart(2, "0")}-01`,
|
|
96
|
+
const baseModel = {
|
|
77
97
|
wageAmount: wage,
|
|
78
|
-
cumulativeIncomeTaxBase: 0,
|
|
79
|
-
cumulativeMinWageIncomeTaxBase: 0,
|
|
80
98
|
ssiType: mapSSIType(ssiType),
|
|
81
99
|
wageCalculationType: mapCalculationType(calculationType),
|
|
82
100
|
wagePeriodType: PaymentPeriodType.Monthly,
|
|
83
|
-
periodCount,
|
|
84
101
|
periodLengthType: PeriodLengthType.Month,
|
|
85
102
|
payments,
|
|
86
103
|
calculationParams: {
|
|
@@ -88,16 +105,40 @@ async function calculatePayroll(client, input) {
|
|
|
88
105
|
customGlobalParams: buildCustomGlobalParams(customParams)
|
|
89
106
|
}
|
|
90
107
|
};
|
|
91
|
-
const result = await client.calculate(model);
|
|
92
108
|
let totalCost = 0;
|
|
93
109
|
let totalNet = 0;
|
|
94
110
|
let totalGross = 0;
|
|
95
111
|
const periods = [];
|
|
96
|
-
|
|
112
|
+
let incomeTaxBase = cumulativeIncomeTaxBase;
|
|
113
|
+
let minWageIncomeTaxBase = cumulativeMinWageIncomeTaxBase;
|
|
114
|
+
let transferredBase1 = transferredSSIBase1;
|
|
115
|
+
let transferredBase2 = transferredSSIBase2;
|
|
116
|
+
for (let i = 0; i < periodCount; i++) {
|
|
117
|
+
const calcDate = new Date(year, month - 1 + i, 1);
|
|
118
|
+
const calcYear = calcDate.getFullYear();
|
|
119
|
+
const calcMonth = calcDate.getMonth() + 1;
|
|
120
|
+
const model = {
|
|
121
|
+
...baseModel,
|
|
122
|
+
calcDate: `${calcYear}-${String(calcMonth).padStart(2, "0")}-01`,
|
|
123
|
+
cumulativeIncomeTaxBase: incomeTaxBase,
|
|
124
|
+
cumulativeMinWageIncomeTaxBase: minWageIncomeTaxBase,
|
|
125
|
+
transferredSSIBase1: transferredBase1,
|
|
126
|
+
transferredSSIBase2: transferredBase2,
|
|
127
|
+
periodCount: 1
|
|
128
|
+
};
|
|
129
|
+
const result = await client.calculate(model);
|
|
130
|
+
const payroll = result.payrolls?.[0];
|
|
131
|
+
if (!payroll) {
|
|
132
|
+
throw new Error("Payrolla calculation returned no payroll data");
|
|
133
|
+
}
|
|
97
134
|
const pr = payroll.payrollResult;
|
|
98
135
|
totalCost += payroll.totalCost;
|
|
99
136
|
totalNet += pr.totalNet;
|
|
100
137
|
totalGross += pr.totalGross;
|
|
138
|
+
const nextIncomeTaxBase = incomeTaxBase + pr.totalIncomeTaxBase;
|
|
139
|
+
const nextMinWageIncomeTaxBase = pr.totalMinWageIncomeTaxExemptionBase;
|
|
140
|
+
const nextTransferredBase1 = pr.transferredSSIBase1 ?? transferredBase1;
|
|
141
|
+
const nextTransferredBase2 = pr.transferredSSIBase2 ?? transferredBase2;
|
|
101
142
|
periods.push({
|
|
102
143
|
year: payroll.year,
|
|
103
144
|
month: payroll.month,
|
|
@@ -107,8 +148,16 @@ async function calculatePayroll(client, input) {
|
|
|
107
148
|
incomeTax: pr.totalIncomeTax,
|
|
108
149
|
stampTax: pr.totalStampTax,
|
|
109
150
|
employeeSSI: pr.totalSSIWorkerPrem,
|
|
110
|
-
employerSSI: pr.totalSSIEmployerPrem
|
|
151
|
+
employerSSI: pr.totalSSIEmployerPrem,
|
|
152
|
+
cumulativeIncomeTaxBase: nextIncomeTaxBase,
|
|
153
|
+
cumulativeMinWageIncomeTaxBase: nextMinWageIncomeTaxBase,
|
|
154
|
+
transferredSSIBase1: nextTransferredBase1,
|
|
155
|
+
transferredSSIBase2: nextTransferredBase2
|
|
111
156
|
});
|
|
157
|
+
incomeTaxBase = nextIncomeTaxBase;
|
|
158
|
+
minWageIncomeTaxBase = nextMinWageIncomeTaxBase;
|
|
159
|
+
transferredBase1 = nextTransferredBase1;
|
|
160
|
+
transferredBase2 = nextTransferredBase2;
|
|
112
161
|
}
|
|
113
162
|
return {
|
|
114
163
|
employee: name,
|
|
@@ -134,7 +183,11 @@ async function calculateBulkPayroll(client, input) {
|
|
|
134
183
|
month,
|
|
135
184
|
periodCount,
|
|
136
185
|
extraPayments: emp.extraPayments,
|
|
137
|
-
customParams
|
|
186
|
+
customParams,
|
|
187
|
+
cumulativeIncomeTaxBase: emp.cumulativeIncomeTaxBase,
|
|
188
|
+
cumulativeMinWageIncomeTaxBase: emp.cumulativeMinWageIncomeTaxBase,
|
|
189
|
+
transferredSSIBase1: emp.transferredSSIBase1,
|
|
190
|
+
transferredSSIBase2: emp.transferredSSIBase2
|
|
138
191
|
});
|
|
139
192
|
employeeResults.push({
|
|
140
193
|
name: result.employee,
|
|
@@ -228,34 +281,68 @@ async function simulateBudget(client, input) {
|
|
|
228
281
|
const { employees, year, periodCount, scenario } = input;
|
|
229
282
|
const defaults = getDefaultParams({ year });
|
|
230
283
|
const customParams = applyScenario(defaults, scenario);
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
284
|
+
const employeeResults = [];
|
|
285
|
+
let totalYearlyCost = 0;
|
|
286
|
+
let totalYearlyNet = 0;
|
|
287
|
+
let totalYearlyGross = 0;
|
|
288
|
+
for (const emp of employees) {
|
|
289
|
+
const adjustedWage = applyRaise(emp.wage, scenario.salaryRaisePercent);
|
|
290
|
+
let cumulativeIncomeTaxBase = 0;
|
|
291
|
+
let cumulativeMinWageIncomeTaxBase = 0;
|
|
292
|
+
let transferredSSIBase1 = 0;
|
|
293
|
+
let transferredSSIBase2 = 0;
|
|
294
|
+
let empTotalCost = 0;
|
|
295
|
+
let empTotalNet = 0;
|
|
296
|
+
let empTotalGross = 0;
|
|
297
|
+
for (let i = 0; i < periodCount; i++) {
|
|
298
|
+
const calcDate = new Date(year, i, 1);
|
|
299
|
+
const calcYear = calcDate.getFullYear();
|
|
300
|
+
const calcMonth = calcDate.getMonth() + 1;
|
|
301
|
+
const periodPayEvents = (emp.payEvents || []).filter(
|
|
302
|
+
(pe) => pe.year === calcYear && pe.month === calcMonth
|
|
303
|
+
);
|
|
304
|
+
const extraPayments = periodPayEvents.map((pe) => ({
|
|
305
|
+
name: pe.name,
|
|
306
|
+
amount: pe.amount,
|
|
307
|
+
type: pe.type,
|
|
308
|
+
paymentType: pe.paymentType
|
|
309
|
+
}));
|
|
310
|
+
const result = await calculatePayroll(client, {
|
|
311
|
+
name: emp.name,
|
|
312
|
+
wage: adjustedWage,
|
|
313
|
+
calculationType: emp.calculationType,
|
|
314
|
+
ssiType: emp.ssiType,
|
|
315
|
+
year: calcYear,
|
|
316
|
+
month: calcMonth,
|
|
317
|
+
periodCount: 1,
|
|
318
|
+
extraPayments: extraPayments.length > 0 ? extraPayments : void 0,
|
|
319
|
+
customParams,
|
|
320
|
+
cumulativeIncomeTaxBase,
|
|
321
|
+
cumulativeMinWageIncomeTaxBase,
|
|
322
|
+
transferredSSIBase1,
|
|
323
|
+
transferredSSIBase2
|
|
324
|
+
});
|
|
325
|
+
empTotalCost += result.totalCost;
|
|
326
|
+
empTotalNet += result.totalNet;
|
|
327
|
+
empTotalGross += result.totalGross;
|
|
328
|
+
const lastPeriod = result.periods[0];
|
|
329
|
+
cumulativeIncomeTaxBase = lastPeriod.cumulativeIncomeTaxBase;
|
|
330
|
+
cumulativeMinWageIncomeTaxBase = lastPeriod.cumulativeMinWageIncomeTaxBase;
|
|
331
|
+
transferredSSIBase1 = lastPeriod.transferredSSIBase1;
|
|
332
|
+
transferredSSIBase2 = lastPeriod.transferredSSIBase2;
|
|
333
|
+
}
|
|
334
|
+
employeeResults.push({
|
|
251
335
|
name: emp.name,
|
|
252
|
-
originalWage: emp.
|
|
253
|
-
adjustedWage
|
|
254
|
-
yearlyCost:
|
|
255
|
-
yearlyNet:
|
|
256
|
-
yearlyGross:
|
|
257
|
-
};
|
|
258
|
-
|
|
336
|
+
originalWage: emp.wage,
|
|
337
|
+
adjustedWage,
|
|
338
|
+
yearlyCost: empTotalCost,
|
|
339
|
+
yearlyNet: empTotalNet,
|
|
340
|
+
yearlyGross: empTotalGross
|
|
341
|
+
});
|
|
342
|
+
totalYearlyCost += empTotalCost;
|
|
343
|
+
totalYearlyNet += empTotalNet;
|
|
344
|
+
totalYearlyGross += empTotalGross;
|
|
345
|
+
}
|
|
259
346
|
const effectiveTaxBrackets = customParams.incomeTaxLimits || defaults.incomeTaxBrackets.map((b) => ({
|
|
260
347
|
limit: b.limit,
|
|
261
348
|
rate: b.rate
|
|
@@ -267,10 +354,10 @@ async function simulateBudget(client, input) {
|
|
|
267
354
|
effectiveTaxBrackets
|
|
268
355
|
},
|
|
269
356
|
summary: {
|
|
270
|
-
totalYearlyCost
|
|
271
|
-
totalYearlyNet
|
|
272
|
-
totalYearlyGross
|
|
273
|
-
costPerEmployee:
|
|
357
|
+
totalYearlyCost,
|
|
358
|
+
totalYearlyNet,
|
|
359
|
+
totalYearlyGross,
|
|
360
|
+
costPerEmployee: totalYearlyCost / employees.length
|
|
274
361
|
},
|
|
275
362
|
employees: employeeResults
|
|
276
363
|
};
|
|
@@ -492,7 +579,28 @@ function registerPrompts(server) {
|
|
|
492
579
|
var ExtraPaymentSchema = z2.object({
|
|
493
580
|
name: z2.string().describe("Name of the extra payment"),
|
|
494
581
|
amount: z2.number().describe("Payment amount"),
|
|
495
|
-
type: z2.enum(["Net", "Gross"]).describe("Payment type")
|
|
582
|
+
type: z2.enum(["Net", "Gross"]).describe("Payment type"),
|
|
583
|
+
paymentType: z2.union([
|
|
584
|
+
z2.literal(1),
|
|
585
|
+
z2.literal(2),
|
|
586
|
+
z2.literal(3),
|
|
587
|
+
z2.literal(4),
|
|
588
|
+
z2.enum(["RegularPayment", "Overtime", "SocialAid", "ExtraPay"])
|
|
589
|
+
]).optional().describe("Payment type (1: RegularPayment, 2: Overtime, 3: SocialAid, 4: ExtraPay)")
|
|
590
|
+
});
|
|
591
|
+
var PayEventSchema = z2.object({
|
|
592
|
+
month: z2.number().min(1).max(12).describe("Month when the payment occurs (1-12)"),
|
|
593
|
+
year: z2.number().describe("Year when the payment occurs"),
|
|
594
|
+
name: z2.string().describe('Payment name (e.g., "Q2 Bonus")'),
|
|
595
|
+
amount: z2.number().describe("Payment amount"),
|
|
596
|
+
type: z2.enum(["Net", "Gross"]).describe("Whether the amount is net or gross"),
|
|
597
|
+
paymentType: z2.union([
|
|
598
|
+
z2.literal(1),
|
|
599
|
+
z2.literal(2),
|
|
600
|
+
z2.literal(3),
|
|
601
|
+
z2.literal(4),
|
|
602
|
+
z2.enum(["RegularPayment", "Overtime", "SocialAid", "ExtraPay"])
|
|
603
|
+
]).optional().describe("Payment category: 1/RegularPayment, 2/Overtime, 3/SocialAid, 4/ExtraPay (default: 4)")
|
|
496
604
|
});
|
|
497
605
|
var CustomParamsSchema = z2.object({
|
|
498
606
|
minWage: z2.number().optional().describe("Custom minimum wage (gross)"),
|
|
@@ -510,7 +618,11 @@ var EmployeeInputSchema = z2.object({
|
|
|
510
618
|
wage: z2.number().describe("Wage amount"),
|
|
511
619
|
calculationType: z2.enum(["Gross", "Net"]).describe("Whether wage is gross or net"),
|
|
512
620
|
ssiType: z2.enum(["S4A", "S4B", "S4C"]).optional().describe("SSI type (default: S4A)"),
|
|
513
|
-
extraPayments: z2.array(ExtraPaymentSchema).optional().describe("Extra payments like bonuses")
|
|
621
|
+
extraPayments: z2.array(ExtraPaymentSchema).optional().describe("Extra payments like bonuses"),
|
|
622
|
+
cumulativeIncomeTaxBase: z2.number().optional().describe("Starting cumulative income tax base"),
|
|
623
|
+
cumulativeMinWageIncomeTaxBase: z2.number().optional().describe("Starting cumulative minimum wage income tax base"),
|
|
624
|
+
transferredSSIBase1: z2.number().optional().describe("Starting transferred SSI base 1"),
|
|
625
|
+
transferredSSIBase2: z2.number().optional().describe("Starting transferred SSI base 2")
|
|
514
626
|
});
|
|
515
627
|
var ScenarioConfigSchema = z2.object({
|
|
516
628
|
name: z2.string().optional().describe("Scenario name for comparison"),
|
|
@@ -556,7 +668,11 @@ function registerTools(server, client) {
|
|
|
556
668
|
month: z2.number().min(1).max(12).describe("Starting month (1-12)"),
|
|
557
669
|
periodCount: z2.number().min(1).max(12).optional().describe("Number of months to calculate (default: 1)"),
|
|
558
670
|
extraPayments: z2.array(ExtraPaymentSchema).optional().describe("Extra payments like bonuses"),
|
|
559
|
-
customParams: CustomParamsSchema.optional().describe("Custom global parameters to override defaults")
|
|
671
|
+
customParams: CustomParamsSchema.optional().describe("Custom global parameters to override defaults"),
|
|
672
|
+
cumulativeIncomeTaxBase: z2.number().optional().describe("Starting cumulative income tax base to carry from previous months"),
|
|
673
|
+
cumulativeMinWageIncomeTaxBase: z2.number().optional().describe("Starting cumulative minimum wage income tax base"),
|
|
674
|
+
transferredSSIBase1: z2.number().optional().describe("Starting transferred SSI base 1"),
|
|
675
|
+
transferredSSIBase2: z2.number().optional().describe("Starting transferred SSI base 2")
|
|
560
676
|
},
|
|
561
677
|
async (params) => {
|
|
562
678
|
try {
|
|
@@ -623,7 +739,9 @@ function registerTools(server, client) {
|
|
|
623
739
|
employees: z2.array(z2.object({
|
|
624
740
|
name: z2.string().describe("Employee name"),
|
|
625
741
|
wage: z2.number().describe("Current wage amount"),
|
|
626
|
-
calculationType: z2.enum(["Gross", "Net"]).describe("Wage type")
|
|
742
|
+
calculationType: z2.enum(["Gross", "Net"]).describe("Wage type"),
|
|
743
|
+
ssiType: z2.enum(["S4A", "S4B", "S4C"]).optional().describe("SSI type (default: S4A)"),
|
|
744
|
+
payEvents: z2.array(PayEventSchema).optional().describe("Extra payments at specific months (e.g., bonuses)")
|
|
627
745
|
})).describe("Array of employees"),
|
|
628
746
|
year: z2.number().describe("Calculation year"),
|
|
629
747
|
periodCount: z2.number().min(1).max(12).describe("Number of months (use 12 for yearly)"),
|
|
@@ -660,7 +778,9 @@ function registerTools(server, client) {
|
|
|
660
778
|
employees: z2.array(z2.object({
|
|
661
779
|
name: z2.string().describe("Employee name"),
|
|
662
780
|
wage: z2.number().describe("Current wage"),
|
|
663
|
-
calculationType: z2.enum(["Gross", "Net"]).describe("Wage type")
|
|
781
|
+
calculationType: z2.enum(["Gross", "Net"]).describe("Wage type"),
|
|
782
|
+
ssiType: z2.enum(["S4A", "S4B", "S4C"]).optional().describe("SSI type (default: S4A)"),
|
|
783
|
+
payEvents: z2.array(PayEventSchema).optional().describe("Extra payments at specific months (e.g., bonuses)")
|
|
664
784
|
})).describe("Array of employees"),
|
|
665
785
|
year: z2.number().describe("Calculation year"),
|
|
666
786
|
periodCount: z2.number().min(1).max(12).describe("Number of months"),
|
package/package.json
CHANGED