@helpu/headless-loan-calculator 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COMMERCIAL-LICENSING.md +17 -0
- package/LICENSE +64 -0
- package/README.md +290 -0
- package/dist/calculator.d.ts +8 -0
- package/dist/calculator.d.ts.map +1 -0
- package/dist/currency.d.ts +7 -0
- package/dist/currency.d.ts.map +1 -0
- package/dist/index.cjs +610 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +598 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +75 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/types.ts
|
|
3
|
+
const VAT_RATES = {
|
|
4
|
+
NoVat: {
|
|
5
|
+
rate: 0,
|
|
6
|
+
label: "No VAT"
|
|
7
|
+
},
|
|
8
|
+
DE: {
|
|
9
|
+
rate: .19,
|
|
10
|
+
label: "Germany (19%)"
|
|
11
|
+
},
|
|
12
|
+
UK: {
|
|
13
|
+
rate: .2,
|
|
14
|
+
label: "UK (20%)"
|
|
15
|
+
},
|
|
16
|
+
FR: {
|
|
17
|
+
rate: .2,
|
|
18
|
+
label: "France (20%)"
|
|
19
|
+
},
|
|
20
|
+
EU: {
|
|
21
|
+
rate: .21,
|
|
22
|
+
label: "EU Standard (21%)"
|
|
23
|
+
},
|
|
24
|
+
IT: {
|
|
25
|
+
rate: .22,
|
|
26
|
+
label: "Italy (22%)"
|
|
27
|
+
},
|
|
28
|
+
ES: {
|
|
29
|
+
rate: .21,
|
|
30
|
+
label: "Spain (21%)"
|
|
31
|
+
},
|
|
32
|
+
HU: {
|
|
33
|
+
rate: .27,
|
|
34
|
+
label: "Hungary (27%)"
|
|
35
|
+
},
|
|
36
|
+
Custom: {
|
|
37
|
+
rate: 0,
|
|
38
|
+
label: "Custom Rate"
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/calculator.ts
|
|
43
|
+
function validateInput(input) {
|
|
44
|
+
const { price, loanTermMonths, apr, initialPayment = 0, residualValue = 0, loanType } = input;
|
|
45
|
+
if (typeof price !== "number" || isNaN(price) || price <= 0) return {
|
|
46
|
+
code: "INVALID_PRICE",
|
|
47
|
+
message: "Price must be a positive number",
|
|
48
|
+
field: "price"
|
|
49
|
+
};
|
|
50
|
+
if (typeof loanTermMonths !== "number" || isNaN(loanTermMonths) || loanTermMonths <= 0 || !Number.isInteger(loanTermMonths)) return {
|
|
51
|
+
code: "INVALID_TERM",
|
|
52
|
+
message: "Loan term must be a positive integer (months)",
|
|
53
|
+
field: "loanTermMonths"
|
|
54
|
+
};
|
|
55
|
+
if (typeof apr !== "number" || isNaN(apr) || apr < 0) return {
|
|
56
|
+
code: "INVALID_APR",
|
|
57
|
+
message: "APR must be a non-negative number",
|
|
58
|
+
field: "apr"
|
|
59
|
+
};
|
|
60
|
+
if (initialPayment >= price) return {
|
|
61
|
+
code: "INITIAL_PAYMENT_TOO_HIGH",
|
|
62
|
+
message: "Initial payment cannot be greater than or equal to the total price",
|
|
63
|
+
field: "initialPayment"
|
|
64
|
+
};
|
|
65
|
+
if ((loanType === "open" ? residualValue : 0) >= price - initialPayment) return {
|
|
66
|
+
code: "RESIDUAL_VALUE_TOO_HIGH",
|
|
67
|
+
message: "Residual value cannot be greater than or equal to the price minus initial payment",
|
|
68
|
+
field: "residualValue"
|
|
69
|
+
};
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
function calculateMonthlyPayment(principal, monthlyRate, termMonths) {
|
|
73
|
+
if (monthlyRate === 0) return principal / termMonths;
|
|
74
|
+
const factor = Math.pow(1 + monthlyRate, termMonths);
|
|
75
|
+
return principal * (monthlyRate * factor) / (factor - 1);
|
|
76
|
+
}
|
|
77
|
+
function calculateLoan(input) {
|
|
78
|
+
const validationError = validateInput(input);
|
|
79
|
+
if (validationError) return {
|
|
80
|
+
success: false,
|
|
81
|
+
error: validationError
|
|
82
|
+
};
|
|
83
|
+
const { price, loanTermMonths, apr, initialPayment = 0, residualValue: inputResidualValue = 0, loanType, priceMode, vatRate } = input;
|
|
84
|
+
const residualValue = loanType === "open" ? inputResidualValue : 0;
|
|
85
|
+
let netAmount;
|
|
86
|
+
let grossAmount;
|
|
87
|
+
if (priceMode === "gross") {
|
|
88
|
+
grossAmount = price;
|
|
89
|
+
netAmount = grossAmount / (1 + vatRate);
|
|
90
|
+
} else {
|
|
91
|
+
netAmount = price;
|
|
92
|
+
grossAmount = netAmount * (1 + vatRate);
|
|
93
|
+
}
|
|
94
|
+
let initialPaymentGross;
|
|
95
|
+
let initialPaymentNet;
|
|
96
|
+
if (priceMode === "gross") {
|
|
97
|
+
initialPaymentGross = initialPayment;
|
|
98
|
+
initialPaymentNet = initialPaymentGross / (1 + vatRate);
|
|
99
|
+
} else {
|
|
100
|
+
initialPaymentNet = initialPayment;
|
|
101
|
+
initialPaymentGross = initialPaymentNet * (1 + vatRate);
|
|
102
|
+
}
|
|
103
|
+
let residualValueGross;
|
|
104
|
+
let residualValueNet;
|
|
105
|
+
if (priceMode === "gross") {
|
|
106
|
+
residualValueGross = residualValue;
|
|
107
|
+
residualValueNet = residualValueGross / (1 + vatRate);
|
|
108
|
+
} else {
|
|
109
|
+
residualValueNet = residualValue;
|
|
110
|
+
residualValueGross = residualValueNet * (1 + vatRate);
|
|
111
|
+
}
|
|
112
|
+
const vatOnInitialPayment = initialPaymentGross - initialPaymentNet;
|
|
113
|
+
const vatOnResidualValue = residualValueGross - residualValueNet;
|
|
114
|
+
const vatOnFinancedAmount = grossAmount - netAmount - vatOnInitialPayment - vatOnResidualValue;
|
|
115
|
+
const totalVatAmount = vatOnInitialPayment + vatOnResidualValue + vatOnFinancedAmount;
|
|
116
|
+
const financedGrossAmount = grossAmount - initialPaymentGross;
|
|
117
|
+
const financedNetAmount = loanType === "closed" ? netAmount - initialPaymentNet : netAmount - initialPaymentNet - residualValueNet;
|
|
118
|
+
const monthlyInterestRate = apr / 12 / 100;
|
|
119
|
+
const monthlyPaymentNet = calculateMonthlyPayment(priceMode === "net" ? financedNetAmount : financedGrossAmount, monthlyInterestRate, loanTermMonths);
|
|
120
|
+
const monthlyPaymentForCalc = priceMode === "net" ? monthlyPaymentNet : monthlyPaymentNet / (1 + vatRate);
|
|
121
|
+
const payments = [];
|
|
122
|
+
let totalInterestAmount = 0;
|
|
123
|
+
let remainingGrossBalance;
|
|
124
|
+
let remainingNetBalance;
|
|
125
|
+
if (loanType === "closed") {
|
|
126
|
+
remainingGrossBalance = grossAmount - initialPaymentGross;
|
|
127
|
+
remainingNetBalance = netAmount - initialPaymentNet;
|
|
128
|
+
} else {
|
|
129
|
+
remainingGrossBalance = grossAmount - initialPaymentGross - residualValueGross;
|
|
130
|
+
remainingNetBalance = netAmount - initialPaymentNet - residualValueNet;
|
|
131
|
+
}
|
|
132
|
+
const totalFinancedAmount = priceMode === "gross" ? financedGrossAmount : financedNetAmount;
|
|
133
|
+
for (let i = 1; i <= loanTermMonths; i++) {
|
|
134
|
+
const interestPayment = priceMode === "net" ? remainingNetBalance * monthlyInterestRate : remainingGrossBalance * monthlyInterestRate;
|
|
135
|
+
const netPrincipalPayment = priceMode === "net" ? monthlyPaymentForCalc - interestPayment : monthlyPaymentForCalc - interestPayment / (1 + vatRate);
|
|
136
|
+
remainingNetBalance -= netPrincipalPayment;
|
|
137
|
+
const vatPayment = netPrincipalPayment * vatRate;
|
|
138
|
+
const grossPrincipalPayment = netPrincipalPayment * (1 + vatRate);
|
|
139
|
+
const grossInterestPayment = priceMode === "net" ? interestPayment * (1 + vatRate) : interestPayment;
|
|
140
|
+
remainingGrossBalance -= grossPrincipalPayment;
|
|
141
|
+
const monthlyPayment = grossPrincipalPayment + grossInterestPayment;
|
|
142
|
+
totalInterestAmount += interestPayment;
|
|
143
|
+
payments.push({
|
|
144
|
+
month: i,
|
|
145
|
+
netAmount: parseFloat(netPrincipalPayment.toFixed(2)),
|
|
146
|
+
vatAmount: parseFloat(vatPayment.toFixed(2)),
|
|
147
|
+
grossAmount: parseFloat(grossPrincipalPayment.toFixed(2)),
|
|
148
|
+
interestAmount: parseFloat(interestPayment.toFixed(2)),
|
|
149
|
+
monthlyPayment: parseFloat(monthlyPayment.toFixed(2)),
|
|
150
|
+
principalBalance: parseFloat(Math.max(0, priceMode === "net" ? remainingNetBalance : remainingGrossBalance).toFixed(2))
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if (initialPayment > 0) payments.unshift({
|
|
154
|
+
month: 0,
|
|
155
|
+
netAmount: parseFloat(initialPaymentNet.toFixed(2)),
|
|
156
|
+
vatAmount: parseFloat((initialPaymentNet * vatRate).toFixed(2)),
|
|
157
|
+
grossAmount: parseFloat(initialPaymentGross.toFixed(2)),
|
|
158
|
+
interestAmount: 0,
|
|
159
|
+
monthlyPayment: parseFloat(initialPaymentGross.toFixed(2)),
|
|
160
|
+
principalBalance: parseFloat((priceMode === "net" ? financedNetAmount : financedGrossAmount).toFixed(2))
|
|
161
|
+
});
|
|
162
|
+
if (loanType === "open" && residualValue > 0) payments.push({
|
|
163
|
+
month: loanTermMonths + 1,
|
|
164
|
+
netAmount: parseFloat(residualValueNet.toFixed(2)),
|
|
165
|
+
vatAmount: parseFloat((residualValueNet * vatRate).toFixed(2)),
|
|
166
|
+
grossAmount: parseFloat(residualValueGross.toFixed(2)),
|
|
167
|
+
interestAmount: 0,
|
|
168
|
+
monthlyPayment: parseFloat(residualValueGross.toFixed(2)),
|
|
169
|
+
principalBalance: 0
|
|
170
|
+
});
|
|
171
|
+
const regularMonthlyPayment = payments.find((p) => p.month === 1).monthlyPayment;
|
|
172
|
+
return {
|
|
173
|
+
success: true,
|
|
174
|
+
data: {
|
|
175
|
+
totalFinancedAmount: parseFloat(totalFinancedAmount.toFixed(2)),
|
|
176
|
+
totalInterestAmount: parseFloat(totalInterestAmount.toFixed(2)),
|
|
177
|
+
totalVatAmount: parseFloat(totalVatAmount.toFixed(2)),
|
|
178
|
+
totalRepayment: parseFloat((totalFinancedAmount + totalInterestAmount + residualValue).toFixed(2)),
|
|
179
|
+
monthlyPayment: parseFloat(regularMonthlyPayment.toFixed(2)),
|
|
180
|
+
paymentSchedule: payments,
|
|
181
|
+
input
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function calculateAffordableLoan(monthlyPayment, monthlyRate, termMonths) {
|
|
186
|
+
if (monthlyRate === 0) return monthlyPayment * termMonths;
|
|
187
|
+
const factor = Math.pow(1 + monthlyRate, termMonths);
|
|
188
|
+
return monthlyPayment * (factor - 1) / (monthlyRate * factor);
|
|
189
|
+
}
|
|
190
|
+
function calculateTotalInterest(principal, monthlyPayment, termMonths) {
|
|
191
|
+
return monthlyPayment * termMonths - principal;
|
|
192
|
+
}
|
|
193
|
+
function getVatRate(vatRateKey, customRate) {
|
|
194
|
+
const VAT_RATES = {
|
|
195
|
+
NoVat: 0,
|
|
196
|
+
DE: .19,
|
|
197
|
+
UK: .2,
|
|
198
|
+
FR: .2,
|
|
199
|
+
EU: .21,
|
|
200
|
+
IT: .22,
|
|
201
|
+
ES: .21,
|
|
202
|
+
HU: .27,
|
|
203
|
+
Custom: 0
|
|
204
|
+
};
|
|
205
|
+
if (vatRateKey === "Custom" && customRate !== void 0) return customRate / 100;
|
|
206
|
+
return VAT_RATES[vatRateKey] ?? 0;
|
|
207
|
+
}
|
|
208
|
+
//#endregion
|
|
209
|
+
//#region src/currency.ts
|
|
210
|
+
const CURRENCY_CONFIG = {
|
|
211
|
+
EUR: {
|
|
212
|
+
symbol: "€",
|
|
213
|
+
code: "EUR",
|
|
214
|
+
name: "Euro",
|
|
215
|
+
region: "Europe",
|
|
216
|
+
position: "after",
|
|
217
|
+
decimalPlaces: 2,
|
|
218
|
+
thousandsSeparator: " ",
|
|
219
|
+
decimalSeparator: ","
|
|
220
|
+
},
|
|
221
|
+
GBP: {
|
|
222
|
+
symbol: "£",
|
|
223
|
+
code: "GBP",
|
|
224
|
+
name: "British Pound",
|
|
225
|
+
region: "Europe",
|
|
226
|
+
position: "before",
|
|
227
|
+
decimalPlaces: 2,
|
|
228
|
+
thousandsSeparator: ",",
|
|
229
|
+
decimalSeparator: "."
|
|
230
|
+
},
|
|
231
|
+
HUF: {
|
|
232
|
+
symbol: "Ft",
|
|
233
|
+
code: "HUF",
|
|
234
|
+
name: "Hungarian Forint",
|
|
235
|
+
region: "Europe",
|
|
236
|
+
position: "after",
|
|
237
|
+
decimalPlaces: 0,
|
|
238
|
+
thousandsSeparator: " ",
|
|
239
|
+
decimalSeparator: ","
|
|
240
|
+
},
|
|
241
|
+
CHF: {
|
|
242
|
+
symbol: "CHF",
|
|
243
|
+
code: "CHF",
|
|
244
|
+
name: "Swiss Franc",
|
|
245
|
+
region: "Europe",
|
|
246
|
+
position: "after",
|
|
247
|
+
decimalPlaces: 2,
|
|
248
|
+
thousandsSeparator: "'",
|
|
249
|
+
decimalSeparator: "."
|
|
250
|
+
},
|
|
251
|
+
SEK: {
|
|
252
|
+
symbol: "kr",
|
|
253
|
+
code: "SEK",
|
|
254
|
+
name: "Swedish Krona",
|
|
255
|
+
region: "Europe",
|
|
256
|
+
position: "after",
|
|
257
|
+
decimalPlaces: 2,
|
|
258
|
+
thousandsSeparator: " ",
|
|
259
|
+
decimalSeparator: ","
|
|
260
|
+
},
|
|
261
|
+
NOK: {
|
|
262
|
+
symbol: "kr",
|
|
263
|
+
code: "NOK",
|
|
264
|
+
name: "Norwegian Krone",
|
|
265
|
+
region: "Europe",
|
|
266
|
+
position: "after",
|
|
267
|
+
decimalPlaces: 2,
|
|
268
|
+
thousandsSeparator: " ",
|
|
269
|
+
decimalSeparator: ","
|
|
270
|
+
},
|
|
271
|
+
DKK: {
|
|
272
|
+
symbol: "kr",
|
|
273
|
+
code: "DKK",
|
|
274
|
+
name: "Danish Krone",
|
|
275
|
+
region: "Europe",
|
|
276
|
+
position: "after",
|
|
277
|
+
decimalPlaces: 2,
|
|
278
|
+
thousandsSeparator: ".",
|
|
279
|
+
decimalSeparator: ","
|
|
280
|
+
},
|
|
281
|
+
PLN: {
|
|
282
|
+
symbol: "zł",
|
|
283
|
+
code: "PLN",
|
|
284
|
+
name: "Polish Złoty",
|
|
285
|
+
region: "Europe",
|
|
286
|
+
position: "after",
|
|
287
|
+
decimalPlaces: 2,
|
|
288
|
+
thousandsSeparator: " ",
|
|
289
|
+
decimalSeparator: ","
|
|
290
|
+
},
|
|
291
|
+
CZK: {
|
|
292
|
+
symbol: "Kč",
|
|
293
|
+
code: "CZK",
|
|
294
|
+
name: "Czech Koruna",
|
|
295
|
+
region: "Europe",
|
|
296
|
+
position: "after",
|
|
297
|
+
decimalPlaces: 2,
|
|
298
|
+
thousandsSeparator: " ",
|
|
299
|
+
decimalSeparator: ","
|
|
300
|
+
},
|
|
301
|
+
RON: {
|
|
302
|
+
symbol: "lei",
|
|
303
|
+
code: "RON",
|
|
304
|
+
name: "Romanian Leu",
|
|
305
|
+
region: "Europe",
|
|
306
|
+
position: "after",
|
|
307
|
+
decimalPlaces: 2,
|
|
308
|
+
thousandsSeparator: ".",
|
|
309
|
+
decimalSeparator: ","
|
|
310
|
+
},
|
|
311
|
+
USD: {
|
|
312
|
+
symbol: "$",
|
|
313
|
+
code: "USD",
|
|
314
|
+
name: "US Dollar",
|
|
315
|
+
region: "Americas",
|
|
316
|
+
position: "before",
|
|
317
|
+
decimalPlaces: 2,
|
|
318
|
+
thousandsSeparator: ",",
|
|
319
|
+
decimalSeparator: "."
|
|
320
|
+
},
|
|
321
|
+
CAD: {
|
|
322
|
+
symbol: "$",
|
|
323
|
+
code: "CAD",
|
|
324
|
+
name: "Canadian Dollar",
|
|
325
|
+
region: "Americas",
|
|
326
|
+
position: "before",
|
|
327
|
+
decimalPlaces: 2,
|
|
328
|
+
thousandsSeparator: ",",
|
|
329
|
+
decimalSeparator: "."
|
|
330
|
+
},
|
|
331
|
+
MXN: {
|
|
332
|
+
symbol: "$",
|
|
333
|
+
code: "MXN",
|
|
334
|
+
name: "Mexican Peso",
|
|
335
|
+
region: "Americas",
|
|
336
|
+
position: "before",
|
|
337
|
+
decimalPlaces: 2,
|
|
338
|
+
thousandsSeparator: ",",
|
|
339
|
+
decimalSeparator: "."
|
|
340
|
+
},
|
|
341
|
+
BRL: {
|
|
342
|
+
symbol: "R$",
|
|
343
|
+
code: "BRL",
|
|
344
|
+
name: "Brazilian Real",
|
|
345
|
+
region: "Americas",
|
|
346
|
+
position: "before",
|
|
347
|
+
decimalPlaces: 2,
|
|
348
|
+
thousandsSeparator: ".",
|
|
349
|
+
decimalSeparator: ","
|
|
350
|
+
},
|
|
351
|
+
ARS: {
|
|
352
|
+
symbol: "$",
|
|
353
|
+
code: "ARS",
|
|
354
|
+
name: "Argentine Peso",
|
|
355
|
+
region: "Americas",
|
|
356
|
+
position: "before",
|
|
357
|
+
decimalPlaces: 2,
|
|
358
|
+
thousandsSeparator: ".",
|
|
359
|
+
decimalSeparator: ","
|
|
360
|
+
},
|
|
361
|
+
CLP: {
|
|
362
|
+
symbol: "$",
|
|
363
|
+
code: "CLP",
|
|
364
|
+
name: "Chilean Peso",
|
|
365
|
+
region: "Americas",
|
|
366
|
+
position: "before",
|
|
367
|
+
decimalPlaces: 0,
|
|
368
|
+
thousandsSeparator: ".",
|
|
369
|
+
decimalSeparator: ","
|
|
370
|
+
},
|
|
371
|
+
COP: {
|
|
372
|
+
symbol: "$",
|
|
373
|
+
code: "COP",
|
|
374
|
+
name: "Colombian Peso",
|
|
375
|
+
region: "Americas",
|
|
376
|
+
position: "before",
|
|
377
|
+
decimalPlaces: 2,
|
|
378
|
+
thousandsSeparator: ".",
|
|
379
|
+
decimalSeparator: ","
|
|
380
|
+
},
|
|
381
|
+
PEN: {
|
|
382
|
+
symbol: "S/",
|
|
383
|
+
code: "PEN",
|
|
384
|
+
name: "Peruvian Sol",
|
|
385
|
+
region: "Americas",
|
|
386
|
+
position: "before",
|
|
387
|
+
decimalPlaces: 2,
|
|
388
|
+
thousandsSeparator: ",",
|
|
389
|
+
decimalSeparator: "."
|
|
390
|
+
},
|
|
391
|
+
JPY: {
|
|
392
|
+
symbol: "¥",
|
|
393
|
+
code: "JPY",
|
|
394
|
+
name: "Japanese Yen",
|
|
395
|
+
region: "Asia",
|
|
396
|
+
position: "before",
|
|
397
|
+
decimalPlaces: 0,
|
|
398
|
+
thousandsSeparator: ",",
|
|
399
|
+
decimalSeparator: "."
|
|
400
|
+
},
|
|
401
|
+
CNY: {
|
|
402
|
+
symbol: "¥",
|
|
403
|
+
code: "CNY",
|
|
404
|
+
name: "Chinese Yuan",
|
|
405
|
+
region: "Asia",
|
|
406
|
+
position: "before",
|
|
407
|
+
decimalPlaces: 2,
|
|
408
|
+
thousandsSeparator: ",",
|
|
409
|
+
decimalSeparator: "."
|
|
410
|
+
},
|
|
411
|
+
HKD: {
|
|
412
|
+
symbol: "HK$",
|
|
413
|
+
code: "HKD",
|
|
414
|
+
name: "Hong Kong Dollar",
|
|
415
|
+
region: "Asia",
|
|
416
|
+
position: "before",
|
|
417
|
+
decimalPlaces: 2,
|
|
418
|
+
thousandsSeparator: ",",
|
|
419
|
+
decimalSeparator: "."
|
|
420
|
+
},
|
|
421
|
+
KRW: {
|
|
422
|
+
symbol: "₩",
|
|
423
|
+
code: "KRW",
|
|
424
|
+
name: "South Korean Won",
|
|
425
|
+
region: "Asia",
|
|
426
|
+
position: "before",
|
|
427
|
+
decimalPlaces: 0,
|
|
428
|
+
thousandsSeparator: ",",
|
|
429
|
+
decimalSeparator: "."
|
|
430
|
+
},
|
|
431
|
+
SGD: {
|
|
432
|
+
symbol: "$",
|
|
433
|
+
code: "SGD",
|
|
434
|
+
name: "Singapore Dollar",
|
|
435
|
+
region: "Asia",
|
|
436
|
+
position: "before",
|
|
437
|
+
decimalPlaces: 2,
|
|
438
|
+
thousandsSeparator: ",",
|
|
439
|
+
decimalSeparator: "."
|
|
440
|
+
},
|
|
441
|
+
INR: {
|
|
442
|
+
symbol: "₹",
|
|
443
|
+
code: "INR",
|
|
444
|
+
name: "Indian Rupee",
|
|
445
|
+
region: "Asia",
|
|
446
|
+
position: "before",
|
|
447
|
+
decimalPlaces: 2,
|
|
448
|
+
thousandsSeparator: ",",
|
|
449
|
+
decimalSeparator: "."
|
|
450
|
+
},
|
|
451
|
+
THB: {
|
|
452
|
+
symbol: "฿",
|
|
453
|
+
code: "THB",
|
|
454
|
+
name: "Thai Baht",
|
|
455
|
+
region: "Asia",
|
|
456
|
+
position: "before",
|
|
457
|
+
decimalPlaces: 2,
|
|
458
|
+
thousandsSeparator: ",",
|
|
459
|
+
decimalSeparator: "."
|
|
460
|
+
},
|
|
461
|
+
MYR: {
|
|
462
|
+
symbol: "RM",
|
|
463
|
+
code: "MYR",
|
|
464
|
+
name: "Malaysian Ringgit",
|
|
465
|
+
region: "Asia",
|
|
466
|
+
position: "before",
|
|
467
|
+
decimalPlaces: 2,
|
|
468
|
+
thousandsSeparator: ",",
|
|
469
|
+
decimalSeparator: "."
|
|
470
|
+
},
|
|
471
|
+
IDR: {
|
|
472
|
+
symbol: "Rp",
|
|
473
|
+
code: "IDR",
|
|
474
|
+
name: "Indonesian Rupiah",
|
|
475
|
+
region: "Asia",
|
|
476
|
+
position: "before",
|
|
477
|
+
decimalPlaces: 0,
|
|
478
|
+
thousandsSeparator: ".",
|
|
479
|
+
decimalSeparator: ","
|
|
480
|
+
},
|
|
481
|
+
PHP: {
|
|
482
|
+
symbol: "₱",
|
|
483
|
+
code: "PHP",
|
|
484
|
+
name: "Philippine Peso",
|
|
485
|
+
region: "Asia",
|
|
486
|
+
position: "before",
|
|
487
|
+
decimalPlaces: 2,
|
|
488
|
+
thousandsSeparator: ",",
|
|
489
|
+
decimalSeparator: "."
|
|
490
|
+
},
|
|
491
|
+
AED: {
|
|
492
|
+
symbol: "د.إ",
|
|
493
|
+
code: "AED",
|
|
494
|
+
name: "UAE Dirham",
|
|
495
|
+
region: "Middle East and Africa",
|
|
496
|
+
position: "after",
|
|
497
|
+
decimalPlaces: 2,
|
|
498
|
+
thousandsSeparator: ",",
|
|
499
|
+
decimalSeparator: "."
|
|
500
|
+
},
|
|
501
|
+
SAR: {
|
|
502
|
+
symbol: "﷼",
|
|
503
|
+
code: "SAR",
|
|
504
|
+
name: "Saudi Riyal",
|
|
505
|
+
region: "Middle East and Africa",
|
|
506
|
+
position: "after",
|
|
507
|
+
decimalPlaces: 2,
|
|
508
|
+
thousandsSeparator: ",",
|
|
509
|
+
decimalSeparator: "."
|
|
510
|
+
},
|
|
511
|
+
ILS: {
|
|
512
|
+
symbol: "₪",
|
|
513
|
+
code: "ILS",
|
|
514
|
+
name: "Israeli New Shekel",
|
|
515
|
+
region: "Middle East and Africa",
|
|
516
|
+
position: "after",
|
|
517
|
+
decimalPlaces: 2,
|
|
518
|
+
thousandsSeparator: ",",
|
|
519
|
+
decimalSeparator: "."
|
|
520
|
+
},
|
|
521
|
+
ZAR: {
|
|
522
|
+
symbol: "R",
|
|
523
|
+
code: "ZAR",
|
|
524
|
+
name: "South African Rand",
|
|
525
|
+
region: "Middle East and Africa",
|
|
526
|
+
position: "before",
|
|
527
|
+
decimalPlaces: 2,
|
|
528
|
+
thousandsSeparator: " ",
|
|
529
|
+
decimalSeparator: "."
|
|
530
|
+
},
|
|
531
|
+
AUD: {
|
|
532
|
+
symbol: "$",
|
|
533
|
+
code: "AUD",
|
|
534
|
+
name: "Australian Dollar",
|
|
535
|
+
region: "Oceania",
|
|
536
|
+
position: "before",
|
|
537
|
+
decimalPlaces: 2,
|
|
538
|
+
thousandsSeparator: ",",
|
|
539
|
+
decimalSeparator: "."
|
|
540
|
+
},
|
|
541
|
+
NZD: {
|
|
542
|
+
symbol: "$",
|
|
543
|
+
code: "NZD",
|
|
544
|
+
name: "New Zealand Dollar",
|
|
545
|
+
region: "Oceania",
|
|
546
|
+
position: "before",
|
|
547
|
+
decimalPlaces: 2,
|
|
548
|
+
thousandsSeparator: ",",
|
|
549
|
+
decimalSeparator: "."
|
|
550
|
+
},
|
|
551
|
+
RUB: {
|
|
552
|
+
symbol: "₽",
|
|
553
|
+
code: "RUB",
|
|
554
|
+
name: "Russian Ruble",
|
|
555
|
+
region: "Other",
|
|
556
|
+
position: "after",
|
|
557
|
+
decimalPlaces: 2,
|
|
558
|
+
thousandsSeparator: " ",
|
|
559
|
+
decimalSeparator: ","
|
|
560
|
+
},
|
|
561
|
+
TRY: {
|
|
562
|
+
symbol: "₺",
|
|
563
|
+
code: "TRY",
|
|
564
|
+
name: "Turkish Lira",
|
|
565
|
+
region: "Other",
|
|
566
|
+
position: "after",
|
|
567
|
+
decimalPlaces: 2,
|
|
568
|
+
thousandsSeparator: ".",
|
|
569
|
+
decimalSeparator: ","
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
function formatCurrency(currency, amount) {
|
|
573
|
+
const config = CURRENCY_CONFIG[currency];
|
|
574
|
+
let formatted;
|
|
575
|
+
if (config.decimalPlaces === 0 || Number.isInteger(amount)) {
|
|
576
|
+
formatted = Math.round(amount).toString();
|
|
577
|
+
formatted = formatted.replace(/\B(?=(\d{3})+(?!\d))/g, config.thousandsSeparator);
|
|
578
|
+
} else {
|
|
579
|
+
const parts = amount.toFixed(config.decimalPlaces).split(".");
|
|
580
|
+
const integerPart = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, config.thousandsSeparator);
|
|
581
|
+
const decimalPart = parts[1];
|
|
582
|
+
formatted = `${integerPart}${config.decimalSeparator}${decimalPart}`;
|
|
583
|
+
}
|
|
584
|
+
if (config.position === "before") return `${config.symbol}${formatted}`;
|
|
585
|
+
else return `${formatted} ${config.symbol}`;
|
|
586
|
+
}
|
|
587
|
+
function getCurrencyConfig(currency) {
|
|
588
|
+
return CURRENCY_CONFIG[currency];
|
|
589
|
+
}
|
|
590
|
+
function getSupportedCurrencies() {
|
|
591
|
+
return Object.keys(CURRENCY_CONFIG);
|
|
592
|
+
}
|
|
593
|
+
function getCurrenciesByRegion(region) {
|
|
594
|
+
return Object.entries(CURRENCY_CONFIG).filter(([_, config]) => config.region === region).map(([code]) => code);
|
|
595
|
+
}
|
|
596
|
+
//#endregion
|
|
597
|
+
exports.CURRENCY_CONFIG = CURRENCY_CONFIG;
|
|
598
|
+
exports.VAT_RATES = VAT_RATES;
|
|
599
|
+
exports.calculateAffordableLoan = calculateAffordableLoan;
|
|
600
|
+
exports.calculateLoan = calculateLoan;
|
|
601
|
+
exports.calculateMonthlyPayment = calculateMonthlyPayment;
|
|
602
|
+
exports.calculateTotalInterest = calculateTotalInterest;
|
|
603
|
+
exports.formatCurrency = formatCurrency;
|
|
604
|
+
exports.getCurrenciesByRegion = getCurrenciesByRegion;
|
|
605
|
+
exports.getCurrencyConfig = getCurrencyConfig;
|
|
606
|
+
exports.getSupportedCurrencies = getSupportedCurrencies;
|
|
607
|
+
exports.getVatRate = getVatRate;
|
|
608
|
+
exports.validateInput = validateInput;
|
|
609
|
+
|
|
610
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/types.ts","../src/calculator.ts","../src/currency.ts"],"sourcesContent":["export const VAT_RATES = {\n NoVat: { rate: 0.0, label: 'No VAT' },\n DE: { rate: 0.19, label: 'Germany (19%)' },\n UK: { rate: 0.2, label: 'UK (20%)' },\n FR: { rate: 0.2, label: 'France (20%)' },\n EU: { rate: 0.21, label: 'EU Standard (21%)' },\n IT: { rate: 0.22, label: 'Italy (22%)' },\n ES: { rate: 0.21, label: 'Spain (21%)' },\n HU: { rate: 0.27, label: 'Hungary (27%)' },\n Custom: { rate: 0.0, label: 'Custom Rate' },\n} as const\nexport type VATRateKey = keyof typeof VAT_RATES\nexport type PriceMode = 'gross' | 'net'\nexport type LoanType = 'closed' | 'open'\nexport type Currency =\n | 'HUF'\n | 'EUR'\n | 'USD'\n | 'GBP'\n | 'JPY'\n | 'CNY'\n | 'AUD'\n | 'CAD'\n | 'CHF'\n | 'NZD'\n | 'SEK'\n | 'NOK'\n | 'DKK'\n | 'SGD'\n | 'HKD'\n | 'KRW'\n | 'MXN'\n | 'BRL'\n | 'INR'\n | 'RUB'\n | 'ZAR'\n | 'PLN'\n | 'TRY'\n | 'AED'\n | 'SAR'\n | 'THB'\n | 'MYR'\n | 'IDR'\n | 'PHP'\n | 'CZK'\n | 'ILS'\n | 'RON'\n | 'CLP'\n | 'ARS'\n | 'COP'\n | 'PEN'\nexport interface MonthlyPayment {\n month: number\n netAmount: number\n vatAmount: number\n grossAmount: number\n interestAmount: number\n monthlyPayment: number\n principalBalance: number\n}\nexport interface CurrencyConfig {\n symbol: string\n code: string\n name?: string\n position: 'before' | 'after'\n decimalPlaces: number\n thousandsSeparator: string\n decimalSeparator: string\n region?: 'Europe' | 'Americas' | 'Asia' | 'Middle East and Africa' | 'Oceania' | 'Other'\n}\nexport interface LoanCalculationInput {\n price: number\n loanTermMonths: number\n apr: number\n initialPayment?: number\n residualValue?: number\n loanType: LoanType\n priceMode: PriceMode\n vatRate: number\n}\nexport interface LoanCalculationResult {\n totalFinancedAmount: number\n totalInterestAmount: number\n totalVatAmount: number\n totalRepayment: number\n monthlyPayment: number\n paymentSchedule: MonthlyPayment[]\n input: LoanCalculationInput\n}\nexport interface LoanCalculationError {\n code:\n | 'INVALID_PRICE'\n | 'INVALID_TERM'\n | 'INVALID_APR'\n | 'INITIAL_PAYMENT_TOO_HIGH'\n | 'RESIDUAL_VALUE_TOO_HIGH'\n | 'INVALID_INPUT'\n message: string\n field?: string\n}\nexport type LoanCalculationResultOrError =\n | {\n success: true\n data: LoanCalculationResult\n }\n | {\n success: false\n error: LoanCalculationError\n }\n","import type {\n LoanCalculationError,\n LoanCalculationInput,\n LoanCalculationResult,\n LoanCalculationResultOrError,\n MonthlyPayment,\n} from './types'\nexport function validateInput(input: LoanCalculationInput): LoanCalculationError | null {\n const { price, loanTermMonths, apr, initialPayment = 0, residualValue = 0, loanType } = input\n if (typeof price !== 'number' || isNaN(price) || price <= 0) {\n return {\n code: 'INVALID_PRICE',\n message: 'Price must be a positive number',\n field: 'price',\n }\n }\n if (\n typeof loanTermMonths !== 'number' ||\n isNaN(loanTermMonths) ||\n loanTermMonths <= 0 ||\n !Number.isInteger(loanTermMonths)\n ) {\n return {\n code: 'INVALID_TERM',\n message: 'Loan term must be a positive integer (months)',\n field: 'loanTermMonths',\n }\n }\n if (typeof apr !== 'number' || isNaN(apr) || apr < 0) {\n return {\n code: 'INVALID_APR',\n message: 'APR must be a non-negative number',\n field: 'apr',\n }\n }\n if (initialPayment >= price) {\n return {\n code: 'INITIAL_PAYMENT_TOO_HIGH',\n message: 'Initial payment cannot be greater than or equal to the total price',\n field: 'initialPayment',\n }\n }\n const effectiveResidualValue = loanType === 'open' ? residualValue : 0\n if (effectiveResidualValue >= price - initialPayment) {\n return {\n code: 'RESIDUAL_VALUE_TOO_HIGH',\n message: 'Residual value cannot be greater than or equal to the price minus initial payment',\n field: 'residualValue',\n }\n }\n return null\n}\nexport function calculateMonthlyPayment(\n principal: number,\n monthlyRate: number,\n termMonths: number,\n): number {\n if (monthlyRate === 0) {\n return principal / termMonths\n }\n const factor = Math.pow(1 + monthlyRate, termMonths)\n return (principal * (monthlyRate * factor)) / (factor - 1)\n}\nexport function calculateLoan(input: LoanCalculationInput): LoanCalculationResultOrError {\n const validationError = validateInput(input)\n if (validationError) {\n return { success: false, error: validationError }\n }\n const {\n price,\n loanTermMonths,\n apr,\n initialPayment = 0,\n residualValue: inputResidualValue = 0,\n loanType,\n priceMode,\n vatRate,\n } = input\n const residualValue = loanType === 'open' ? inputResidualValue : 0\n let netAmount: number\n let grossAmount: number\n if (priceMode === 'gross') {\n grossAmount = price\n netAmount = grossAmount / (1 + vatRate)\n } else {\n netAmount = price\n grossAmount = netAmount * (1 + vatRate)\n }\n let initialPaymentGross: number\n let initialPaymentNet: number\n if (priceMode === 'gross') {\n initialPaymentGross = initialPayment\n initialPaymentNet = initialPaymentGross / (1 + vatRate)\n } else {\n initialPaymentNet = initialPayment\n initialPaymentGross = initialPaymentNet * (1 + vatRate)\n }\n let residualValueGross: number\n let residualValueNet: number\n if (priceMode === 'gross') {\n residualValueGross = residualValue\n residualValueNet = residualValueGross / (1 + vatRate)\n } else {\n residualValueNet = residualValue\n residualValueGross = residualValueNet * (1 + vatRate)\n }\n const vatOnInitialPayment = initialPaymentGross - initialPaymentNet\n const vatOnResidualValue = residualValueGross - residualValueNet\n const vatOnFinancedAmount = grossAmount - netAmount - vatOnInitialPayment - vatOnResidualValue\n const totalVatAmount = vatOnInitialPayment + vatOnResidualValue + vatOnFinancedAmount\n const financedGrossAmount = grossAmount - initialPaymentGross\n const financedNetAmount =\n loanType === 'closed'\n ? netAmount - initialPaymentNet\n : netAmount - initialPaymentNet - residualValueNet\n const monthlyInterestRate = apr / 12 / 100\n const principalForCalc = priceMode === 'net' ? financedNetAmount : financedGrossAmount\n const monthlyPaymentNet = calculateMonthlyPayment(\n principalForCalc,\n monthlyInterestRate,\n loanTermMonths,\n )\n const monthlyPaymentForCalc =\n priceMode === 'net' ? monthlyPaymentNet : monthlyPaymentNet / (1 + vatRate)\n const payments: MonthlyPayment[] = []\n let totalInterestAmount = 0\n let remainingGrossBalance: number\n let remainingNetBalance: number\n if (loanType === 'closed') {\n remainingGrossBalance = grossAmount - initialPaymentGross\n remainingNetBalance = netAmount - initialPaymentNet\n } else {\n remainingGrossBalance = grossAmount - initialPaymentGross - residualValueGross\n remainingNetBalance = netAmount - initialPaymentNet - residualValueNet\n }\n const totalFinancedAmount = priceMode === 'gross' ? financedGrossAmount : financedNetAmount\n for (let i = 1; i <= loanTermMonths; i++) {\n const interestPayment =\n priceMode === 'net'\n ? remainingNetBalance * monthlyInterestRate\n : remainingGrossBalance * monthlyInterestRate\n const netPrincipalPayment =\n priceMode === 'net'\n ? monthlyPaymentForCalc - interestPayment\n : monthlyPaymentForCalc - interestPayment / (1 + vatRate)\n remainingNetBalance -= netPrincipalPayment\n const vatPayment = netPrincipalPayment * vatRate\n const grossPrincipalPayment = netPrincipalPayment * (1 + vatRate)\n const grossInterestPayment =\n priceMode === 'net' ? interestPayment * (1 + vatRate) : interestPayment\n remainingGrossBalance -= grossPrincipalPayment\n const monthlyPayment = grossPrincipalPayment + grossInterestPayment\n totalInterestAmount += interestPayment\n payments.push({\n month: i,\n netAmount: parseFloat(netPrincipalPayment.toFixed(2)),\n vatAmount: parseFloat(vatPayment.toFixed(2)),\n grossAmount: parseFloat(grossPrincipalPayment.toFixed(2)),\n interestAmount: parseFloat(interestPayment.toFixed(2)),\n monthlyPayment: parseFloat(monthlyPayment.toFixed(2)),\n principalBalance: parseFloat(\n Math.max(0, priceMode === 'net' ? remainingNetBalance : remainingGrossBalance).toFixed(2),\n ),\n })\n }\n if (initialPayment > 0) {\n payments.unshift({\n month: 0,\n netAmount: parseFloat(initialPaymentNet.toFixed(2)),\n vatAmount: parseFloat((initialPaymentNet * vatRate).toFixed(2)),\n grossAmount: parseFloat(initialPaymentGross.toFixed(2)),\n interestAmount: 0,\n monthlyPayment: parseFloat(initialPaymentGross.toFixed(2)),\n principalBalance: parseFloat(\n (priceMode === 'net' ? financedNetAmount : financedGrossAmount).toFixed(2),\n ),\n })\n }\n if (loanType === 'open' && residualValue > 0) {\n payments.push({\n month: loanTermMonths + 1,\n netAmount: parseFloat(residualValueNet.toFixed(2)),\n vatAmount: parseFloat((residualValueNet * vatRate).toFixed(2)),\n grossAmount: parseFloat(residualValueGross.toFixed(2)),\n interestAmount: 0,\n monthlyPayment: parseFloat(residualValueGross.toFixed(2)),\n principalBalance: 0,\n })\n }\n const regularMonthlyPayment = payments.find((p) => p.month === 1)!.monthlyPayment\n const result: LoanCalculationResult = {\n totalFinancedAmount: parseFloat(totalFinancedAmount.toFixed(2)),\n totalInterestAmount: parseFloat(totalInterestAmount.toFixed(2)),\n totalVatAmount: parseFloat(totalVatAmount.toFixed(2)),\n totalRepayment: parseFloat(\n (totalFinancedAmount + totalInterestAmount + residualValue).toFixed(2),\n ),\n monthlyPayment: parseFloat(regularMonthlyPayment.toFixed(2)),\n paymentSchedule: payments,\n input,\n }\n return { success: true, data: result }\n}\nexport function calculateAffordableLoan(\n monthlyPayment: number,\n monthlyRate: number,\n termMonths: number,\n): number {\n if (monthlyRate === 0) {\n return monthlyPayment * termMonths\n }\n const factor = Math.pow(1 + monthlyRate, termMonths)\n return (monthlyPayment * (factor - 1)) / (monthlyRate * factor)\n}\nexport function calculateTotalInterest(\n principal: number,\n monthlyPayment: number,\n termMonths: number,\n): number {\n return monthlyPayment * termMonths - principal\n}\nexport function getVatRate(vatRateKey: string, customRate?: number): number {\n const VAT_RATES: Record<string, number> = {\n NoVat: 0.0,\n DE: 0.19,\n UK: 0.2,\n FR: 0.2,\n EU: 0.21,\n IT: 0.22,\n ES: 0.21,\n HU: 0.27,\n Custom: 0.0,\n }\n if (vatRateKey === 'Custom' && customRate !== undefined) {\n return customRate / 100\n }\n return VAT_RATES[vatRateKey] ?? 0\n}\n","import type { Currency, CurrencyConfig } from './types'\nexport const CURRENCY_CONFIG: Record<Currency, CurrencyConfig> = {\n EUR: {\n symbol: '€',\n code: 'EUR',\n name: 'Euro',\n region: 'Europe',\n position: 'after',\n decimalPlaces: 2,\n thousandsSeparator: ' ',\n decimalSeparator: ',',\n },\n GBP: {\n symbol: '£',\n code: 'GBP',\n name: 'British Pound',\n region: 'Europe',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n HUF: {\n symbol: 'Ft',\n code: 'HUF',\n name: 'Hungarian Forint',\n region: 'Europe',\n position: 'after',\n decimalPlaces: 0,\n thousandsSeparator: ' ',\n decimalSeparator: ',',\n },\n CHF: {\n symbol: 'CHF',\n code: 'CHF',\n name: 'Swiss Franc',\n region: 'Europe',\n position: 'after',\n decimalPlaces: 2,\n thousandsSeparator: \"'\",\n decimalSeparator: '.',\n },\n SEK: {\n symbol: 'kr',\n code: 'SEK',\n name: 'Swedish Krona',\n region: 'Europe',\n position: 'after',\n decimalPlaces: 2,\n thousandsSeparator: ' ',\n decimalSeparator: ',',\n },\n NOK: {\n symbol: 'kr',\n code: 'NOK',\n name: 'Norwegian Krone',\n region: 'Europe',\n position: 'after',\n decimalPlaces: 2,\n thousandsSeparator: ' ',\n decimalSeparator: ',',\n },\n DKK: {\n symbol: 'kr',\n code: 'DKK',\n name: 'Danish Krone',\n region: 'Europe',\n position: 'after',\n decimalPlaces: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n },\n PLN: {\n symbol: 'zł',\n code: 'PLN',\n name: 'Polish Złoty',\n region: 'Europe',\n position: 'after',\n decimalPlaces: 2,\n thousandsSeparator: ' ',\n decimalSeparator: ',',\n },\n CZK: {\n symbol: 'Kč',\n code: 'CZK',\n name: 'Czech Koruna',\n region: 'Europe',\n position: 'after',\n decimalPlaces: 2,\n thousandsSeparator: ' ',\n decimalSeparator: ',',\n },\n RON: {\n symbol: 'lei',\n code: 'RON',\n name: 'Romanian Leu',\n region: 'Europe',\n position: 'after',\n decimalPlaces: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n },\n USD: {\n symbol: '$',\n code: 'USD',\n name: 'US Dollar',\n region: 'Americas',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n CAD: {\n symbol: '$',\n code: 'CAD',\n name: 'Canadian Dollar',\n region: 'Americas',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n MXN: {\n symbol: '$',\n code: 'MXN',\n name: 'Mexican Peso',\n region: 'Americas',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n BRL: {\n symbol: 'R$',\n code: 'BRL',\n name: 'Brazilian Real',\n region: 'Americas',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n },\n ARS: {\n symbol: '$',\n code: 'ARS',\n name: 'Argentine Peso',\n region: 'Americas',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n },\n CLP: {\n symbol: '$',\n code: 'CLP',\n name: 'Chilean Peso',\n region: 'Americas',\n position: 'before',\n decimalPlaces: 0,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n },\n COP: {\n symbol: '$',\n code: 'COP',\n name: 'Colombian Peso',\n region: 'Americas',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n },\n PEN: {\n symbol: 'S/',\n code: 'PEN',\n name: 'Peruvian Sol',\n region: 'Americas',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n JPY: {\n symbol: '¥',\n code: 'JPY',\n name: 'Japanese Yen',\n region: 'Asia',\n position: 'before',\n decimalPlaces: 0,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n CNY: {\n symbol: '¥',\n code: 'CNY',\n name: 'Chinese Yuan',\n region: 'Asia',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n HKD: {\n symbol: 'HK$',\n code: 'HKD',\n name: 'Hong Kong Dollar',\n region: 'Asia',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n KRW: {\n symbol: '₩',\n code: 'KRW',\n name: 'South Korean Won',\n region: 'Asia',\n position: 'before',\n decimalPlaces: 0,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n SGD: {\n symbol: '$',\n code: 'SGD',\n name: 'Singapore Dollar',\n region: 'Asia',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n INR: {\n symbol: '₹',\n code: 'INR',\n name: 'Indian Rupee',\n region: 'Asia',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n THB: {\n symbol: '฿',\n code: 'THB',\n name: 'Thai Baht',\n region: 'Asia',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n MYR: {\n symbol: 'RM',\n code: 'MYR',\n name: 'Malaysian Ringgit',\n region: 'Asia',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n IDR: {\n symbol: 'Rp',\n code: 'IDR',\n name: 'Indonesian Rupiah',\n region: 'Asia',\n position: 'before',\n decimalPlaces: 0,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n },\n PHP: {\n symbol: '₱',\n code: 'PHP',\n name: 'Philippine Peso',\n region: 'Asia',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n AED: {\n symbol: 'د.إ',\n code: 'AED',\n name: 'UAE Dirham',\n region: 'Middle East and Africa',\n position: 'after',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n SAR: {\n symbol: '﷼',\n code: 'SAR',\n name: 'Saudi Riyal',\n region: 'Middle East and Africa',\n position: 'after',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n ILS: {\n symbol: '₪',\n code: 'ILS',\n name: 'Israeli New Shekel',\n region: 'Middle East and Africa',\n position: 'after',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n ZAR: {\n symbol: 'R',\n code: 'ZAR',\n name: 'South African Rand',\n region: 'Middle East and Africa',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ' ',\n decimalSeparator: '.',\n },\n AUD: {\n symbol: '$',\n code: 'AUD',\n name: 'Australian Dollar',\n region: 'Oceania',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n NZD: {\n symbol: '$',\n code: 'NZD',\n name: 'New Zealand Dollar',\n region: 'Oceania',\n position: 'before',\n decimalPlaces: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n },\n RUB: {\n symbol: '₽',\n code: 'RUB',\n name: 'Russian Ruble',\n region: 'Other',\n position: 'after',\n decimalPlaces: 2,\n thousandsSeparator: ' ',\n decimalSeparator: ',',\n },\n TRY: {\n symbol: '₺',\n code: 'TRY',\n name: 'Turkish Lira',\n region: 'Other',\n position: 'after',\n decimalPlaces: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n },\n}\nexport function formatCurrency(currency: Currency, amount: number): string {\n const config = CURRENCY_CONFIG[currency]\n let formatted: string\n if (config.decimalPlaces === 0 || Number.isInteger(amount)) {\n formatted = Math.round(amount).toString()\n formatted = formatted.replace(/\\B(?=(\\d{3})+(?!\\d))/g, config.thousandsSeparator)\n } else {\n const parts = amount.toFixed(config.decimalPlaces).split('.')\n const integerPart = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, config.thousandsSeparator)\n const decimalPart = parts[1]\n formatted = `${integerPart}${config.decimalSeparator}${decimalPart}`\n }\n if (config.position === 'before') {\n return `${config.symbol}${formatted}`\n } else {\n return `${formatted} ${config.symbol}`\n }\n}\nexport function getCurrencyConfig(currency: Currency): CurrencyConfig {\n return CURRENCY_CONFIG[currency]\n}\nexport function getSupportedCurrencies(): Currency[] {\n return Object.keys(CURRENCY_CONFIG) as Currency[]\n}\nexport function getCurrenciesByRegion(region: CurrencyConfig['region']): Currency[] {\n return (Object.entries(CURRENCY_CONFIG) as [Currency, CurrencyConfig][])\n .filter(([_, config]) => config.region === region)\n .map(([code]) => code)\n}\n"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { Currency, CurrencyConfig, LoanCalculationError, LoanCalculationInput, LoanCalculationResult, LoanCalculationResultOrError, LoanType, MonthlyPayment, PriceMode, VATRateKey, } from './types';
|
|
2
|
+
export { VAT_RATES } from './types';
|
|
3
|
+
export { calculateAffordableLoan, calculateLoan, calculateMonthlyPayment, calculateTotalInterest, getVatRate, validateInput, } from './calculator';
|
|
4
|
+
export { CURRENCY_CONFIG, formatCurrency, getCurrenciesByRegion, getCurrencyConfig, getSupportedCurrencies, } from './currency';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,QAAQ,EACR,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,4BAA4B,EAC5B,QAAQ,EACR,cAAc,EACd,SAAS,EACT,UAAU,GACX,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACnC,OAAO,EACL,uBAAuB,EACvB,aAAa,EACb,uBAAuB,EACvB,sBAAsB,EACtB,UAAU,EACV,aAAa,GACd,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,YAAY,CAAA"}
|