bordro 0.1.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.
- package/LICENSE +21 -0
- package/README.md +181 -0
- package/dist/chunk-QFU4FK7O.js +253 -0
- package/dist/cli.cjs +400 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +178 -0
- package/dist/index.cjs +296 -0
- package/dist/index.d.cts +174 -0
- package/dist/index.d.ts +174 -0
- package/dist/index.js +40 -0
- package/package.json +64 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AY_ADLARI: () => AY_ADLARI,
|
|
24
|
+
VARSAYILAN_YIL: () => VARSAYILAN_YIL,
|
|
25
|
+
YILLAR: () => YILLAR,
|
|
26
|
+
YIL_2026: () => YIL_2026,
|
|
27
|
+
brutenNete: () => brutenNete,
|
|
28
|
+
dilimOrani: () => dilimOrani,
|
|
29
|
+
hesapla: () => hesapla,
|
|
30
|
+
isvereneMaliyet: () => isvereneMaliyet,
|
|
31
|
+
kurusaYuvarla: () => kurusaYuvarla,
|
|
32
|
+
nettenBrute: () => nettenBrute,
|
|
33
|
+
primeEsasKazanc: () => primeEsasKazanc,
|
|
34
|
+
sayiyaCevir: () => sayiyaCevir,
|
|
35
|
+
tarifeyeGoreVergi: () => tarifeyeGoreVergi,
|
|
36
|
+
tl: () => tl,
|
|
37
|
+
tlSimgeli: () => tlSimgeli,
|
|
38
|
+
yilParametreleri: () => yilParametreleri,
|
|
39
|
+
yillikHesapla: () => yillikHesapla,
|
|
40
|
+
yuzde: () => yuzde
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(index_exports);
|
|
43
|
+
|
|
44
|
+
// src/veri/2026.ts
|
|
45
|
+
var YIL_2026 = {
|
|
46
|
+
yil: 2026,
|
|
47
|
+
// Gross minimum wage: 33,030.00 TRY/month (28,075.50 TRY net)
|
|
48
|
+
asgariUcretBrut: 33030,
|
|
49
|
+
// Social security earnings: the floor is the minimum wage, the ceiling is 9x that
|
|
50
|
+
sgkTaban: 33030,
|
|
51
|
+
sgkTavan: 297270,
|
|
52
|
+
// Premiums withheld from the employee
|
|
53
|
+
sgkIsciOrani: 0.14,
|
|
54
|
+
issizlikIsciOrani: 0.01,
|
|
55
|
+
// Premiums paid by the employer (20.75% = 11% disability/old age/death + 7.5% health + 2.25% short-term)
|
|
56
|
+
sgkIsverenOrani: 0.2075,
|
|
57
|
+
sgkIsverenIndirimliOrani: 0.1575,
|
|
58
|
+
// law 5510 art. 81-i: the 5-point discount
|
|
59
|
+
issizlikIsverenOrani: 0.02,
|
|
60
|
+
// Stamp duty on wages: 0.759 per cent
|
|
61
|
+
damgaVergisiOrani: 759e-5,
|
|
62
|
+
// The progressive schedule applied to wage income
|
|
63
|
+
gelirVergisiDilimleri: [
|
|
64
|
+
{ ustSinir: 19e4, oran: 0.15 },
|
|
65
|
+
{ ustSinir: 4e5, oran: 0.2 },
|
|
66
|
+
{ ustSinir: 15e5, oran: 0.27 },
|
|
67
|
+
{ ustSinir: 53e5, oran: 0.35 },
|
|
68
|
+
{ ustSinir: Infinity, oran: 0.4 }
|
|
69
|
+
],
|
|
70
|
+
kaynaklar: [
|
|
71
|
+
"Vergi Merkezi \u2014 2026 Pratik Bilgiler: https://vergimerkezi.com.tr/2026-pratik-bilgiler-mali-rehber/",
|
|
72
|
+
"Kolay \u0130K \u2014 2026 gelir vergisi dilimleri: https://kolayik.com/blog/2026-gelir-vergisi-dilimleri-guncel-tablo",
|
|
73
|
+
"Kolay \u0130K \u2014 2026 bordro parametreleri: https://kolayik.com/blog/2026-bordro-parametreleri",
|
|
74
|
+
"CottGroup \u2014 2026 y\u0131l\u0131 bordrodaki yasal kesintiler: https://www.cottgroup.com/tr/mevzuat/item/2026-yili-icin-bordrodaki-yasal-kesintiler"
|
|
75
|
+
]
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// src/hesap.ts
|
|
79
|
+
var YILLAR = {
|
|
80
|
+
2026: YIL_2026
|
|
81
|
+
};
|
|
82
|
+
var VARSAYILAN_YIL = Math.max(...Object.keys(YILLAR).map(Number));
|
|
83
|
+
function kurusaYuvarla(tutar) {
|
|
84
|
+
return Math.round((tutar + Number.EPSILON) * 100) / 100;
|
|
85
|
+
}
|
|
86
|
+
function yilParametreleri(yil = VARSAYILAN_YIL) {
|
|
87
|
+
const p = YILLAR[yil];
|
|
88
|
+
if (!p) {
|
|
89
|
+
const destekli = Object.keys(YILLAR).join(", ");
|
|
90
|
+
throw new Error(`${yil} y\u0131l\u0131 i\xE7in parametre yok. Desteklenen y\u0131llar: ${destekli}`);
|
|
91
|
+
}
|
|
92
|
+
return p;
|
|
93
|
+
}
|
|
94
|
+
function tarifeyeGoreVergi(kumulatifMatrah, dilimler) {
|
|
95
|
+
let vergi = 0;
|
|
96
|
+
let altSinir = 0;
|
|
97
|
+
for (const dilim of dilimler) {
|
|
98
|
+
if (kumulatifMatrah <= altSinir) break;
|
|
99
|
+
const dilimdekiTutar = Math.min(kumulatifMatrah, dilim.ustSinir) - altSinir;
|
|
100
|
+
vergi += dilimdekiTutar * dilim.oran;
|
|
101
|
+
altSinir = dilim.ustSinir;
|
|
102
|
+
}
|
|
103
|
+
return vergi;
|
|
104
|
+
}
|
|
105
|
+
function dilimOrani(kumulatifMatrah, dilimler) {
|
|
106
|
+
for (const dilim of dilimler) {
|
|
107
|
+
if (kumulatifMatrah <= dilim.ustSinir) return dilim.oran;
|
|
108
|
+
}
|
|
109
|
+
return dilimler[dilimler.length - 1]?.oran ?? 0;
|
|
110
|
+
}
|
|
111
|
+
function primeEsasKazanc(brut, p) {
|
|
112
|
+
return Math.min(Math.max(brut, p.sgkTaban), p.sgkTavan);
|
|
113
|
+
}
|
|
114
|
+
function yillikHesapla(brut, secenekler = {}) {
|
|
115
|
+
if (!Number.isFinite(brut) || brut <= 0) {
|
|
116
|
+
throw new Error("Br\xFCt maa\u015F s\u0131f\u0131rdan b\xFCy\xFCk bir say\u0131 olmal\u0131.");
|
|
117
|
+
}
|
|
118
|
+
const p = yilParametreleri(secenekler.yil);
|
|
119
|
+
const istisnaUygula = secenekler.asgariUcretIstisnasi ?? true;
|
|
120
|
+
const asgariMatrah = kurusaYuvarla(
|
|
121
|
+
p.asgariUcretBrut * (1 - p.sgkIsciOrani - p.issizlikIsciOrani)
|
|
122
|
+
);
|
|
123
|
+
const asgariDamga = kurusaYuvarla(p.asgariUcretBrut * p.damgaVergisiOrani);
|
|
124
|
+
const sgkMatrahi = kurusaYuvarla(primeEsasKazanc(brut, p));
|
|
125
|
+
const sgkIsci = kurusaYuvarla(sgkMatrahi * p.sgkIsciOrani);
|
|
126
|
+
const issizlikIsci = kurusaYuvarla(sgkMatrahi * p.issizlikIsciOrani);
|
|
127
|
+
const gelirVergisiMatrahi = kurusaYuvarla(brut - sgkIsci - issizlikIsci);
|
|
128
|
+
const hesaplananDamgaVergisi = kurusaYuvarla(brut * p.damgaVergisiOrani);
|
|
129
|
+
const aylar = [];
|
|
130
|
+
const dilimGecisAylari = [];
|
|
131
|
+
let kumulatif = 0;
|
|
132
|
+
let asgariKumulatif = 0;
|
|
133
|
+
let oncekiDilim = 0;
|
|
134
|
+
for (let ay = 1; ay <= 12; ay++) {
|
|
135
|
+
const oncekiKumulatif = kumulatif;
|
|
136
|
+
kumulatif = kurusaYuvarla(kumulatif + gelirVergisiMatrahi);
|
|
137
|
+
const hesaplananGelirVergisi = kurusaYuvarla(
|
|
138
|
+
tarifeyeGoreVergi(kumulatif, p.gelirVergisiDilimleri) - tarifeyeGoreVergi(oncekiKumulatif, p.gelirVergisiDilimleri)
|
|
139
|
+
);
|
|
140
|
+
const asgariOncekiKumulatif = asgariKumulatif;
|
|
141
|
+
asgariKumulatif = kurusaYuvarla(asgariKumulatif + asgariMatrah);
|
|
142
|
+
const asgariAylikVergi = kurusaYuvarla(
|
|
143
|
+
tarifeyeGoreVergi(asgariKumulatif, p.gelirVergisiDilimleri) - tarifeyeGoreVergi(asgariOncekiKumulatif, p.gelirVergisiDilimleri)
|
|
144
|
+
);
|
|
145
|
+
const gelirVergisiIstisnasi = istisnaUygula ? Math.min(hesaplananGelirVergisi, asgariAylikVergi) : 0;
|
|
146
|
+
const damgaVergisiIstisnasi = istisnaUygula ? Math.min(hesaplananDamgaVergisi, asgariDamga) : 0;
|
|
147
|
+
const gelirVergisi = kurusaYuvarla(hesaplananGelirVergisi - gelirVergisiIstisnasi);
|
|
148
|
+
const damgaVergisi = kurusaYuvarla(hesaplananDamgaVergisi - damgaVergisiIstisnasi);
|
|
149
|
+
const kesintiler = kurusaYuvarla(sgkIsci + issizlikIsci + gelirVergisi + damgaVergisi);
|
|
150
|
+
const net = kurusaYuvarla(brut - kesintiler);
|
|
151
|
+
const buAyinDilimi = dilimOrani(kumulatif, p.gelirVergisiDilimleri);
|
|
152
|
+
const dilimAtladi = ay > 1 && buAyinDilimi > oncekiDilim;
|
|
153
|
+
if (dilimAtladi) dilimGecisAylari.push(ay);
|
|
154
|
+
oncekiDilim = buAyinDilimi;
|
|
155
|
+
aylar.push({
|
|
156
|
+
ay,
|
|
157
|
+
brut,
|
|
158
|
+
sgkMatrahi,
|
|
159
|
+
sgkIsci,
|
|
160
|
+
issizlikIsci,
|
|
161
|
+
gelirVergisiMatrahi,
|
|
162
|
+
kumulatifMatrah: kumulatif,
|
|
163
|
+
hesaplananGelirVergisi,
|
|
164
|
+
gelirVergisiIstisnasi,
|
|
165
|
+
gelirVergisi,
|
|
166
|
+
hesaplananDamgaVergisi,
|
|
167
|
+
damgaVergisiIstisnasi,
|
|
168
|
+
damgaVergisi,
|
|
169
|
+
kesintiler,
|
|
170
|
+
net,
|
|
171
|
+
vergiDilimiOrani: buAyinDilimi,
|
|
172
|
+
dilimAtladi
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
const topla = (secici) => kurusaYuvarla(aylar.reduce((t, a) => t + secici(a), 0));
|
|
176
|
+
const ilkAy = aylar[0];
|
|
177
|
+
const sonAy = aylar[aylar.length - 1];
|
|
178
|
+
return {
|
|
179
|
+
yil: p.yil,
|
|
180
|
+
brut,
|
|
181
|
+
aylar,
|
|
182
|
+
toplam: {
|
|
183
|
+
brut: topla((a) => a.brut),
|
|
184
|
+
sgkIsci: topla((a) => a.sgkIsci),
|
|
185
|
+
issizlikIsci: topla((a) => a.issizlikIsci),
|
|
186
|
+
gelirVergisi: topla((a) => a.gelirVergisi),
|
|
187
|
+
damgaVergisi: topla((a) => a.damgaVergisi),
|
|
188
|
+
kesintiler: topla((a) => a.kesintiler),
|
|
189
|
+
net: topla((a) => a.net)
|
|
190
|
+
},
|
|
191
|
+
dilimGecisAylari,
|
|
192
|
+
netDegisimi: kurusaYuvarla(sonAy.net - ilkAy.net)
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function hesapla(brut, ay = 1, secenekler = {}) {
|
|
196
|
+
if (!Number.isInteger(ay) || ay < 1 || ay > 12) {
|
|
197
|
+
throw new Error("Ay 1 ile 12 aras\u0131nda bir tam say\u0131 olmal\u0131.");
|
|
198
|
+
}
|
|
199
|
+
return yillikHesapla(brut, secenekler).aylar[ay - 1];
|
|
200
|
+
}
|
|
201
|
+
function brutenNete(brut, ay = 1, secenekler = {}) {
|
|
202
|
+
return hesapla(brut, ay, secenekler).net;
|
|
203
|
+
}
|
|
204
|
+
function nettenBrute(net, ay = 1, secenekler = {}) {
|
|
205
|
+
if (!Number.isFinite(net) || net <= 0) {
|
|
206
|
+
throw new Error("Net maa\u015F s\u0131f\u0131rdan b\xFCy\xFCk bir say\u0131 olmal\u0131.");
|
|
207
|
+
}
|
|
208
|
+
let alt = 0;
|
|
209
|
+
let ust = Math.max(net * 3, 1e3);
|
|
210
|
+
while (brutenNete(ust, ay, secenekler) < net) {
|
|
211
|
+
ust *= 2;
|
|
212
|
+
if (ust > 1e12) throw new Error("Net maa\u015F \xE7ok y\xFCksek, br\xFCt kar\u015F\u0131l\u0131\u011F\u0131 bulunamad\u0131.");
|
|
213
|
+
}
|
|
214
|
+
for (let i = 0; i < 60; i++) {
|
|
215
|
+
const orta = (alt + ust) / 2;
|
|
216
|
+
if (brutenNete(orta, ay, secenekler) < net) alt = orta;
|
|
217
|
+
else ust = orta;
|
|
218
|
+
}
|
|
219
|
+
const brut = kurusaYuvarla(ust);
|
|
220
|
+
return brutenNete(brut, ay, secenekler) < net ? kurusaYuvarla(brut + 0.01) : brut;
|
|
221
|
+
}
|
|
222
|
+
function isvereneMaliyet(brut, secenekler = {}) {
|
|
223
|
+
if (!Number.isFinite(brut) || brut <= 0) {
|
|
224
|
+
throw new Error("Br\xFCt maa\u015F s\u0131f\u0131rdan b\xFCy\xFCk bir say\u0131 olmal\u0131.");
|
|
225
|
+
}
|
|
226
|
+
const p = yilParametreleri(secenekler.yil);
|
|
227
|
+
const indirimUygulandi = secenekler.besPuanIndirimi ?? false;
|
|
228
|
+
const sgkMatrahi = kurusaYuvarla(primeEsasKazanc(brut, p));
|
|
229
|
+
const isverenOrani = indirimUygulandi ? p.sgkIsverenIndirimliOrani : p.sgkIsverenOrani;
|
|
230
|
+
const sgkIsveren = kurusaYuvarla(sgkMatrahi * isverenOrani);
|
|
231
|
+
const issizlikIsveren = kurusaYuvarla(sgkMatrahi * p.issizlikIsverenOrani);
|
|
232
|
+
return {
|
|
233
|
+
brut,
|
|
234
|
+
sgkMatrahi,
|
|
235
|
+
sgkIsveren,
|
|
236
|
+
issizlikIsveren,
|
|
237
|
+
toplamMaliyet: kurusaYuvarla(brut + sgkIsveren + issizlikIsveren),
|
|
238
|
+
indirimUygulandi
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// src/bicim.ts
|
|
243
|
+
var TL_BICIMI = new Intl.NumberFormat("tr-TR", {
|
|
244
|
+
minimumFractionDigits: 2,
|
|
245
|
+
maximumFractionDigits: 2
|
|
246
|
+
});
|
|
247
|
+
var AY_ADLARI = [
|
|
248
|
+
"Ocak",
|
|
249
|
+
"\u015Eubat",
|
|
250
|
+
"Mart",
|
|
251
|
+
"Nisan",
|
|
252
|
+
"May\u0131s",
|
|
253
|
+
"Haziran",
|
|
254
|
+
"Temmuz",
|
|
255
|
+
"A\u011Fustos",
|
|
256
|
+
"Eyl\xFCl",
|
|
257
|
+
"Ekim",
|
|
258
|
+
"Kas\u0131m",
|
|
259
|
+
"Aral\u0131k"
|
|
260
|
+
];
|
|
261
|
+
function tl(tutar) {
|
|
262
|
+
return TL_BICIMI.format(tutar);
|
|
263
|
+
}
|
|
264
|
+
function tlSimgeli(tutar) {
|
|
265
|
+
return `${tl(tutar)} \u20BA`;
|
|
266
|
+
}
|
|
267
|
+
function yuzde(oran) {
|
|
268
|
+
return `%${(oran * 100).toLocaleString("tr-TR", { maximumFractionDigits: 2 })}`;
|
|
269
|
+
}
|
|
270
|
+
function sayiyaCevir(girdi) {
|
|
271
|
+
const temiz = girdi.trim().replace(/[\s₺]/g, "").replace(/\./g, "").replace(",", ".");
|
|
272
|
+
const sayi = Number(temiz);
|
|
273
|
+
if (!Number.isFinite(sayi)) throw new Error(`Say\u0131ya \xE7evrilemedi: "${girdi}"`);
|
|
274
|
+
return sayi;
|
|
275
|
+
}
|
|
276
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
277
|
+
0 && (module.exports = {
|
|
278
|
+
AY_ADLARI,
|
|
279
|
+
VARSAYILAN_YIL,
|
|
280
|
+
YILLAR,
|
|
281
|
+
YIL_2026,
|
|
282
|
+
brutenNete,
|
|
283
|
+
dilimOrani,
|
|
284
|
+
hesapla,
|
|
285
|
+
isvereneMaliyet,
|
|
286
|
+
kurusaYuvarla,
|
|
287
|
+
nettenBrute,
|
|
288
|
+
primeEsasKazanc,
|
|
289
|
+
sayiyaCevir,
|
|
290
|
+
tarifeyeGoreVergi,
|
|
291
|
+
tl,
|
|
292
|
+
tlSimgeli,
|
|
293
|
+
yilParametreleri,
|
|
294
|
+
yillikHesapla,
|
|
295
|
+
yuzde
|
|
296
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/** A single bracket of the income tax schedule. */
|
|
2
|
+
interface VergiDilimi {
|
|
3
|
+
/** Upper bound of the bracket (cumulative tax base, TRY). `Infinity` on the last one. */
|
|
4
|
+
ustSinir: number;
|
|
5
|
+
/** Rate applied to the bracket (0.15 = 15%). */
|
|
6
|
+
oran: number;
|
|
7
|
+
}
|
|
8
|
+
/** Every statutory parameter for a given year. */
|
|
9
|
+
interface YilParametreleri {
|
|
10
|
+
yil: number;
|
|
11
|
+
/** Monthly gross minimum wage (TRY). */
|
|
12
|
+
asgariUcretBrut: number;
|
|
13
|
+
/** Lower bound of social security earnings (TRY/month). */
|
|
14
|
+
sgkTaban: number;
|
|
15
|
+
/** Upper bound of social security earnings — the ceiling (TRY/month). */
|
|
16
|
+
sgkTavan: number;
|
|
17
|
+
/** Employee share of the social security premium. */
|
|
18
|
+
sgkIsciOrani: number;
|
|
19
|
+
/** Employee share of the unemployment insurance premium. */
|
|
20
|
+
issizlikIsciOrani: number;
|
|
21
|
+
/** Employer share of the social security premium (without the incentive). */
|
|
22
|
+
sgkIsverenOrani: number;
|
|
23
|
+
/** Employer social security rate when the 5-point discount applies. */
|
|
24
|
+
sgkIsverenIndirimliOrani: number;
|
|
25
|
+
/** Employer share of the unemployment insurance premium. */
|
|
26
|
+
issizlikIsverenOrani: number;
|
|
27
|
+
/** Stamp duty rate on wages (0.759 per cent = 0.00759). */
|
|
28
|
+
damgaVergisiOrani: number;
|
|
29
|
+
/** Income tax schedule applied to wage income, in ascending order. */
|
|
30
|
+
gelirVergisiDilimleri: readonly VergiDilimi[];
|
|
31
|
+
/** Sources the figures were taken from. */
|
|
32
|
+
kaynaklar: readonly string[];
|
|
33
|
+
}
|
|
34
|
+
/** The payroll breakdown of a single month. */
|
|
35
|
+
interface AylikBordro {
|
|
36
|
+
/** Month number, 1 = January. */
|
|
37
|
+
ay: number;
|
|
38
|
+
brut: number;
|
|
39
|
+
/** Social security base: the gross salary clamped between the floor and the ceiling. */
|
|
40
|
+
sgkMatrahi: number;
|
|
41
|
+
sgkIsci: number;
|
|
42
|
+
issizlikIsci: number;
|
|
43
|
+
/** Income tax base: gross minus the social security deductions. */
|
|
44
|
+
gelirVergisiMatrahi: number;
|
|
45
|
+
/** Total income tax base from the start of the year up to this month. */
|
|
46
|
+
kumulatifMatrah: number;
|
|
47
|
+
/** Income tax from the schedule, before the exemption is deducted. */
|
|
48
|
+
hesaplananGelirVergisi: number;
|
|
49
|
+
/** The minimum wage income tax exemption that gets deducted. */
|
|
50
|
+
gelirVergisiIstisnasi: number;
|
|
51
|
+
/** Income tax actually withheld. */
|
|
52
|
+
gelirVergisi: number;
|
|
53
|
+
hesaplananDamgaVergisi: number;
|
|
54
|
+
damgaVergisiIstisnasi: number;
|
|
55
|
+
damgaVergisi: number;
|
|
56
|
+
/** Total deductions. */
|
|
57
|
+
kesintiler: number;
|
|
58
|
+
/** Net pay that reaches the employee. */
|
|
59
|
+
net: number;
|
|
60
|
+
/** Highest income tax rate applied in this month (0.15, 0.20 ...). */
|
|
61
|
+
vergiDilimiOrani: number;
|
|
62
|
+
/** True if this month moved up into a higher tax bracket. */
|
|
63
|
+
dilimAtladi: boolean;
|
|
64
|
+
}
|
|
65
|
+
/** Employer cost breakdown (monthly). */
|
|
66
|
+
interface IsverenMaliyeti {
|
|
67
|
+
brut: number;
|
|
68
|
+
sgkMatrahi: number;
|
|
69
|
+
sgkIsveren: number;
|
|
70
|
+
issizlikIsveren: number;
|
|
71
|
+
/** Gross plus the employer premiums. */
|
|
72
|
+
toplamMaliyet: number;
|
|
73
|
+
/** Was the 5-point discount applied? */
|
|
74
|
+
indirimUygulandi: boolean;
|
|
75
|
+
}
|
|
76
|
+
/** Result of the annual calculation. */
|
|
77
|
+
interface YillikSonuc {
|
|
78
|
+
yil: number;
|
|
79
|
+
brut: number;
|
|
80
|
+
aylar: AylikBordro[];
|
|
81
|
+
/** Annual totals. */
|
|
82
|
+
toplam: {
|
|
83
|
+
brut: number;
|
|
84
|
+
sgkIsci: number;
|
|
85
|
+
issizlikIsci: number;
|
|
86
|
+
gelirVergisi: number;
|
|
87
|
+
damgaVergisi: number;
|
|
88
|
+
kesintiler: number;
|
|
89
|
+
net: number;
|
|
90
|
+
};
|
|
91
|
+
/** Months in which the tax bracket changed (1 = January). */
|
|
92
|
+
dilimGecisAylari: number[];
|
|
93
|
+
/** Difference between December net and January net (usually negative). */
|
|
94
|
+
netDegisimi: number;
|
|
95
|
+
}
|
|
96
|
+
/** Calculation options. */
|
|
97
|
+
interface HesapSecenekleri {
|
|
98
|
+
/** Year to calculate. Defaults to the most recent supported year. */
|
|
99
|
+
yil?: number;
|
|
100
|
+
/**
|
|
101
|
+
* Apply the minimum wage income/stamp duty exemption?
|
|
102
|
+
* It has applied to every wage earner since 2022; defaults to `true`.
|
|
103
|
+
*/
|
|
104
|
+
asgariUcretIstisnasi?: boolean;
|
|
105
|
+
/** Apply the 5-point discount to the employer social security share? Defaults to `false`. */
|
|
106
|
+
besPuanIndirimi?: boolean;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Supported years. Adding a new year is one line here. */
|
|
110
|
+
declare const YILLAR: Record<number, YilParametreleri>;
|
|
111
|
+
/** The most recent year that has a parameter file. */
|
|
112
|
+
declare const VARSAYILAN_YIL: number;
|
|
113
|
+
/** Rounds an amount to the kuruş. Every payroll line is rounded to 2 decimals. */
|
|
114
|
+
declare function kurusaYuvarla(tutar: number): number;
|
|
115
|
+
declare function yilParametreleri(yil?: number): YilParametreleri;
|
|
116
|
+
/**
|
|
117
|
+
* Total income tax from the schedule for a given cumulative tax base.
|
|
118
|
+
*
|
|
119
|
+
* Tax accumulates from the start of the year, so a single month's tax is
|
|
120
|
+
* "total tax up to this month − total tax up to last month".
|
|
121
|
+
*/
|
|
122
|
+
declare function tarifeyeGoreVergi(kumulatifMatrah: number, dilimler: readonly VergiDilimi[]): number;
|
|
123
|
+
/** Returns the tax bracket the cumulative base falls into. */
|
|
124
|
+
declare function dilimOrani(kumulatifMatrah: number, dilimler: readonly VergiDilimi[]): number;
|
|
125
|
+
/** Clamps the gross salary between the social security floor and ceiling. */
|
|
126
|
+
declare function primeEsasKazanc(brut: number, p: YilParametreleri): number;
|
|
127
|
+
/**
|
|
128
|
+
* Calculates the twelve-month payroll.
|
|
129
|
+
*
|
|
130
|
+
* Income tax in Turkey accumulates across the year, so even when the gross
|
|
131
|
+
* salary never changes the net pay drops in the month the higher bracket is
|
|
132
|
+
* reached. This function computes every month separately to make that visible.
|
|
133
|
+
*/
|
|
134
|
+
declare function yillikHesapla(brut: number, secenekler?: HesapSecenekleri): YillikSonuc;
|
|
135
|
+
/**
|
|
136
|
+
* Calculates the payroll for a single month.
|
|
137
|
+
*
|
|
138
|
+
* @param brut Monthly gross wage
|
|
139
|
+
* @param ay Month of the year (1 = January). The result depends on the month because tax is cumulative.
|
|
140
|
+
*/
|
|
141
|
+
declare function hesapla(brut: number, ay?: number, secenekler?: HesapSecenekleri): AylikBordro;
|
|
142
|
+
/** Gross to net: returns only the take-home amount. */
|
|
143
|
+
declare function brutenNete(brut: number, ay?: number, secenekler?: HesapSecenekleri): number;
|
|
144
|
+
/**
|
|
145
|
+
* Converts net to gross.
|
|
146
|
+
*
|
|
147
|
+
* The deductions are progressive, so there is no closed-form inverse; a binary
|
|
148
|
+
* search converges on the answer to the kuruş.
|
|
149
|
+
*/
|
|
150
|
+
declare function nettenBrute(net: number, ay?: number, secenekler?: HesapSecenekleri): number;
|
|
151
|
+
/** Monthly employer cost: gross plus the employer premiums. */
|
|
152
|
+
declare function isvereneMaliyet(brut: number, secenekler?: HesapSecenekleri): IsverenMaliyeti;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Payroll parameters for 2026.
|
|
156
|
+
*
|
|
157
|
+
* Every figure here comes from an official source and is covered by a test:
|
|
158
|
+
* `test/asgari-ucret.test.ts` checks that the minimum wage earner's net comes
|
|
159
|
+
* out at exactly 28,075.50 TRY. Get one number wrong and that test breaks.
|
|
160
|
+
*/
|
|
161
|
+
declare const YIL_2026: YilParametreleri;
|
|
162
|
+
|
|
163
|
+
/** Number and text formatting helpers, shared by the CLI and the web page. */
|
|
164
|
+
declare const AY_ADLARI: readonly ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"];
|
|
165
|
+
/** 57339.5 → "57.339,50" */
|
|
166
|
+
declare function tl(tutar: number): string;
|
|
167
|
+
/** 57339.5 → "57.339,50 ₺" */
|
|
168
|
+
declare function tlSimgeli(tutar: number): string;
|
|
169
|
+
/** 0.15 → "%15" */
|
|
170
|
+
declare function yuzde(oran: number): string;
|
|
171
|
+
/** Parses user input such as "75.000,50" / "75000" / "75 000" into a number. */
|
|
172
|
+
declare function sayiyaCevir(girdi: string): number;
|
|
173
|
+
|
|
174
|
+
export { AY_ADLARI, type AylikBordro, type HesapSecenekleri, type IsverenMaliyeti, VARSAYILAN_YIL, type VergiDilimi, YILLAR, YIL_2026, type YilParametreleri, type YillikSonuc, brutenNete, dilimOrani, hesapla, isvereneMaliyet, kurusaYuvarla, nettenBrute, primeEsasKazanc, sayiyaCevir, tarifeyeGoreVergi, tl, tlSimgeli, yilParametreleri, yillikHesapla, yuzde };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/** A single bracket of the income tax schedule. */
|
|
2
|
+
interface VergiDilimi {
|
|
3
|
+
/** Upper bound of the bracket (cumulative tax base, TRY). `Infinity` on the last one. */
|
|
4
|
+
ustSinir: number;
|
|
5
|
+
/** Rate applied to the bracket (0.15 = 15%). */
|
|
6
|
+
oran: number;
|
|
7
|
+
}
|
|
8
|
+
/** Every statutory parameter for a given year. */
|
|
9
|
+
interface YilParametreleri {
|
|
10
|
+
yil: number;
|
|
11
|
+
/** Monthly gross minimum wage (TRY). */
|
|
12
|
+
asgariUcretBrut: number;
|
|
13
|
+
/** Lower bound of social security earnings (TRY/month). */
|
|
14
|
+
sgkTaban: number;
|
|
15
|
+
/** Upper bound of social security earnings — the ceiling (TRY/month). */
|
|
16
|
+
sgkTavan: number;
|
|
17
|
+
/** Employee share of the social security premium. */
|
|
18
|
+
sgkIsciOrani: number;
|
|
19
|
+
/** Employee share of the unemployment insurance premium. */
|
|
20
|
+
issizlikIsciOrani: number;
|
|
21
|
+
/** Employer share of the social security premium (without the incentive). */
|
|
22
|
+
sgkIsverenOrani: number;
|
|
23
|
+
/** Employer social security rate when the 5-point discount applies. */
|
|
24
|
+
sgkIsverenIndirimliOrani: number;
|
|
25
|
+
/** Employer share of the unemployment insurance premium. */
|
|
26
|
+
issizlikIsverenOrani: number;
|
|
27
|
+
/** Stamp duty rate on wages (0.759 per cent = 0.00759). */
|
|
28
|
+
damgaVergisiOrani: number;
|
|
29
|
+
/** Income tax schedule applied to wage income, in ascending order. */
|
|
30
|
+
gelirVergisiDilimleri: readonly VergiDilimi[];
|
|
31
|
+
/** Sources the figures were taken from. */
|
|
32
|
+
kaynaklar: readonly string[];
|
|
33
|
+
}
|
|
34
|
+
/** The payroll breakdown of a single month. */
|
|
35
|
+
interface AylikBordro {
|
|
36
|
+
/** Month number, 1 = January. */
|
|
37
|
+
ay: number;
|
|
38
|
+
brut: number;
|
|
39
|
+
/** Social security base: the gross salary clamped between the floor and the ceiling. */
|
|
40
|
+
sgkMatrahi: number;
|
|
41
|
+
sgkIsci: number;
|
|
42
|
+
issizlikIsci: number;
|
|
43
|
+
/** Income tax base: gross minus the social security deductions. */
|
|
44
|
+
gelirVergisiMatrahi: number;
|
|
45
|
+
/** Total income tax base from the start of the year up to this month. */
|
|
46
|
+
kumulatifMatrah: number;
|
|
47
|
+
/** Income tax from the schedule, before the exemption is deducted. */
|
|
48
|
+
hesaplananGelirVergisi: number;
|
|
49
|
+
/** The minimum wage income tax exemption that gets deducted. */
|
|
50
|
+
gelirVergisiIstisnasi: number;
|
|
51
|
+
/** Income tax actually withheld. */
|
|
52
|
+
gelirVergisi: number;
|
|
53
|
+
hesaplananDamgaVergisi: number;
|
|
54
|
+
damgaVergisiIstisnasi: number;
|
|
55
|
+
damgaVergisi: number;
|
|
56
|
+
/** Total deductions. */
|
|
57
|
+
kesintiler: number;
|
|
58
|
+
/** Net pay that reaches the employee. */
|
|
59
|
+
net: number;
|
|
60
|
+
/** Highest income tax rate applied in this month (0.15, 0.20 ...). */
|
|
61
|
+
vergiDilimiOrani: number;
|
|
62
|
+
/** True if this month moved up into a higher tax bracket. */
|
|
63
|
+
dilimAtladi: boolean;
|
|
64
|
+
}
|
|
65
|
+
/** Employer cost breakdown (monthly). */
|
|
66
|
+
interface IsverenMaliyeti {
|
|
67
|
+
brut: number;
|
|
68
|
+
sgkMatrahi: number;
|
|
69
|
+
sgkIsveren: number;
|
|
70
|
+
issizlikIsveren: number;
|
|
71
|
+
/** Gross plus the employer premiums. */
|
|
72
|
+
toplamMaliyet: number;
|
|
73
|
+
/** Was the 5-point discount applied? */
|
|
74
|
+
indirimUygulandi: boolean;
|
|
75
|
+
}
|
|
76
|
+
/** Result of the annual calculation. */
|
|
77
|
+
interface YillikSonuc {
|
|
78
|
+
yil: number;
|
|
79
|
+
brut: number;
|
|
80
|
+
aylar: AylikBordro[];
|
|
81
|
+
/** Annual totals. */
|
|
82
|
+
toplam: {
|
|
83
|
+
brut: number;
|
|
84
|
+
sgkIsci: number;
|
|
85
|
+
issizlikIsci: number;
|
|
86
|
+
gelirVergisi: number;
|
|
87
|
+
damgaVergisi: number;
|
|
88
|
+
kesintiler: number;
|
|
89
|
+
net: number;
|
|
90
|
+
};
|
|
91
|
+
/** Months in which the tax bracket changed (1 = January). */
|
|
92
|
+
dilimGecisAylari: number[];
|
|
93
|
+
/** Difference between December net and January net (usually negative). */
|
|
94
|
+
netDegisimi: number;
|
|
95
|
+
}
|
|
96
|
+
/** Calculation options. */
|
|
97
|
+
interface HesapSecenekleri {
|
|
98
|
+
/** Year to calculate. Defaults to the most recent supported year. */
|
|
99
|
+
yil?: number;
|
|
100
|
+
/**
|
|
101
|
+
* Apply the minimum wage income/stamp duty exemption?
|
|
102
|
+
* It has applied to every wage earner since 2022; defaults to `true`.
|
|
103
|
+
*/
|
|
104
|
+
asgariUcretIstisnasi?: boolean;
|
|
105
|
+
/** Apply the 5-point discount to the employer social security share? Defaults to `false`. */
|
|
106
|
+
besPuanIndirimi?: boolean;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Supported years. Adding a new year is one line here. */
|
|
110
|
+
declare const YILLAR: Record<number, YilParametreleri>;
|
|
111
|
+
/** The most recent year that has a parameter file. */
|
|
112
|
+
declare const VARSAYILAN_YIL: number;
|
|
113
|
+
/** Rounds an amount to the kuruş. Every payroll line is rounded to 2 decimals. */
|
|
114
|
+
declare function kurusaYuvarla(tutar: number): number;
|
|
115
|
+
declare function yilParametreleri(yil?: number): YilParametreleri;
|
|
116
|
+
/**
|
|
117
|
+
* Total income tax from the schedule for a given cumulative tax base.
|
|
118
|
+
*
|
|
119
|
+
* Tax accumulates from the start of the year, so a single month's tax is
|
|
120
|
+
* "total tax up to this month − total tax up to last month".
|
|
121
|
+
*/
|
|
122
|
+
declare function tarifeyeGoreVergi(kumulatifMatrah: number, dilimler: readonly VergiDilimi[]): number;
|
|
123
|
+
/** Returns the tax bracket the cumulative base falls into. */
|
|
124
|
+
declare function dilimOrani(kumulatifMatrah: number, dilimler: readonly VergiDilimi[]): number;
|
|
125
|
+
/** Clamps the gross salary between the social security floor and ceiling. */
|
|
126
|
+
declare function primeEsasKazanc(brut: number, p: YilParametreleri): number;
|
|
127
|
+
/**
|
|
128
|
+
* Calculates the twelve-month payroll.
|
|
129
|
+
*
|
|
130
|
+
* Income tax in Turkey accumulates across the year, so even when the gross
|
|
131
|
+
* salary never changes the net pay drops in the month the higher bracket is
|
|
132
|
+
* reached. This function computes every month separately to make that visible.
|
|
133
|
+
*/
|
|
134
|
+
declare function yillikHesapla(brut: number, secenekler?: HesapSecenekleri): YillikSonuc;
|
|
135
|
+
/**
|
|
136
|
+
* Calculates the payroll for a single month.
|
|
137
|
+
*
|
|
138
|
+
* @param brut Monthly gross wage
|
|
139
|
+
* @param ay Month of the year (1 = January). The result depends on the month because tax is cumulative.
|
|
140
|
+
*/
|
|
141
|
+
declare function hesapla(brut: number, ay?: number, secenekler?: HesapSecenekleri): AylikBordro;
|
|
142
|
+
/** Gross to net: returns only the take-home amount. */
|
|
143
|
+
declare function brutenNete(brut: number, ay?: number, secenekler?: HesapSecenekleri): number;
|
|
144
|
+
/**
|
|
145
|
+
* Converts net to gross.
|
|
146
|
+
*
|
|
147
|
+
* The deductions are progressive, so there is no closed-form inverse; a binary
|
|
148
|
+
* search converges on the answer to the kuruş.
|
|
149
|
+
*/
|
|
150
|
+
declare function nettenBrute(net: number, ay?: number, secenekler?: HesapSecenekleri): number;
|
|
151
|
+
/** Monthly employer cost: gross plus the employer premiums. */
|
|
152
|
+
declare function isvereneMaliyet(brut: number, secenekler?: HesapSecenekleri): IsverenMaliyeti;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Payroll parameters for 2026.
|
|
156
|
+
*
|
|
157
|
+
* Every figure here comes from an official source and is covered by a test:
|
|
158
|
+
* `test/asgari-ucret.test.ts` checks that the minimum wage earner's net comes
|
|
159
|
+
* out at exactly 28,075.50 TRY. Get one number wrong and that test breaks.
|
|
160
|
+
*/
|
|
161
|
+
declare const YIL_2026: YilParametreleri;
|
|
162
|
+
|
|
163
|
+
/** Number and text formatting helpers, shared by the CLI and the web page. */
|
|
164
|
+
declare const AY_ADLARI: readonly ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"];
|
|
165
|
+
/** 57339.5 → "57.339,50" */
|
|
166
|
+
declare function tl(tutar: number): string;
|
|
167
|
+
/** 57339.5 → "57.339,50 ₺" */
|
|
168
|
+
declare function tlSimgeli(tutar: number): string;
|
|
169
|
+
/** 0.15 → "%15" */
|
|
170
|
+
declare function yuzde(oran: number): string;
|
|
171
|
+
/** Parses user input such as "75.000,50" / "75000" / "75 000" into a number. */
|
|
172
|
+
declare function sayiyaCevir(girdi: string): number;
|
|
173
|
+
|
|
174
|
+
export { AY_ADLARI, type AylikBordro, type HesapSecenekleri, type IsverenMaliyeti, VARSAYILAN_YIL, type VergiDilimi, YILLAR, YIL_2026, type YilParametreleri, type YillikSonuc, brutenNete, dilimOrani, hesapla, isvereneMaliyet, kurusaYuvarla, nettenBrute, primeEsasKazanc, sayiyaCevir, tarifeyeGoreVergi, tl, tlSimgeli, yilParametreleri, yillikHesapla, yuzde };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AY_ADLARI,
|
|
3
|
+
VARSAYILAN_YIL,
|
|
4
|
+
YILLAR,
|
|
5
|
+
YIL_2026,
|
|
6
|
+
brutenNete,
|
|
7
|
+
dilimOrani,
|
|
8
|
+
hesapla,
|
|
9
|
+
isvereneMaliyet,
|
|
10
|
+
kurusaYuvarla,
|
|
11
|
+
nettenBrute,
|
|
12
|
+
primeEsasKazanc,
|
|
13
|
+
sayiyaCevir,
|
|
14
|
+
tarifeyeGoreVergi,
|
|
15
|
+
tl,
|
|
16
|
+
tlSimgeli,
|
|
17
|
+
yilParametreleri,
|
|
18
|
+
yillikHesapla,
|
|
19
|
+
yuzde
|
|
20
|
+
} from "./chunk-QFU4FK7O.js";
|
|
21
|
+
export {
|
|
22
|
+
AY_ADLARI,
|
|
23
|
+
VARSAYILAN_YIL,
|
|
24
|
+
YILLAR,
|
|
25
|
+
YIL_2026,
|
|
26
|
+
brutenNete,
|
|
27
|
+
dilimOrani,
|
|
28
|
+
hesapla,
|
|
29
|
+
isvereneMaliyet,
|
|
30
|
+
kurusaYuvarla,
|
|
31
|
+
nettenBrute,
|
|
32
|
+
primeEsasKazanc,
|
|
33
|
+
sayiyaCevir,
|
|
34
|
+
tarifeyeGoreVergi,
|
|
35
|
+
tl,
|
|
36
|
+
tlSimgeli,
|
|
37
|
+
yilParametreleri,
|
|
38
|
+
yillikHesapla,
|
|
39
|
+
yuzde
|
|
40
|
+
};
|