@jjlmoya/utils-finance 1.34.0 → 1.36.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/package.json +1 -1
- package/src/category/index.ts +2 -1
- package/src/entries.ts +5 -1
- package/src/index.ts +1 -0
- package/src/pages/[locale]/[slug].astro +1 -1
- package/src/tests/locale_completeness.test.ts +2 -2
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tool/inflationPurchasingPower/bibliography.astro +14 -0
- package/src/tool/inflationPurchasingPower/bibliography.ts +12 -0
- package/src/tool/inflationPurchasingPower/component.astro +79 -0
- package/src/tool/inflationPurchasingPower/controller.ts +82 -0
- package/src/tool/inflationPurchasingPower/dom-views.ts +99 -0
- package/src/tool/inflationPurchasingPower/entry.ts +31 -0
- package/src/tool/inflationPurchasingPower/evaluator.ts +18 -0
- package/src/tool/inflationPurchasingPower/i18n/de.ts +56 -0
- package/src/tool/inflationPurchasingPower/i18n/en.ts +131 -0
- package/src/tool/inflationPurchasingPower/i18n/es.ts +44 -0
- package/src/tool/inflationPurchasingPower/i18n/fr.ts +44 -0
- package/src/tool/inflationPurchasingPower/i18n/id.ts +44 -0
- package/src/tool/inflationPurchasingPower/i18n/it.ts +44 -0
- package/src/tool/inflationPurchasingPower/i18n/ja.ts +44 -0
- package/src/tool/inflationPurchasingPower/i18n/ko.ts +44 -0
- package/src/tool/inflationPurchasingPower/i18n/nl.ts +44 -0
- package/src/tool/inflationPurchasingPower/i18n/pl.ts +44 -0
- package/src/tool/inflationPurchasingPower/i18n/pt.ts +44 -0
- package/src/tool/inflationPurchasingPower/i18n/ru.ts +44 -0
- package/src/tool/inflationPurchasingPower/i18n/sv.ts +44 -0
- package/src/tool/inflationPurchasingPower/i18n/tr.ts +44 -0
- package/src/tool/inflationPurchasingPower/i18n/zh.ts +44 -0
- package/src/tool/inflationPurchasingPower/index.ts +11 -0
- package/src/tool/inflationPurchasingPower/inflation-purchasing-power-timeline.css +402 -0
- package/src/tool/inflationPurchasingPower/logic.test.ts +35 -0
- package/src/tool/inflationPurchasingPower/logic.ts +92 -0
- package/src/tool/inflationPurchasingPower/seo.astro +14 -0
- package/src/tool/inflationPurchasingPower/storage.ts +29 -0
- package/src/tool/inflationPurchasingPower/ui.ts +42 -0
- package/src/tool/mortgageExtraPaymentPlanner/bibliography.astro +14 -0
- package/src/tool/mortgageExtraPaymentPlanner/bibliography.ts +12 -0
- package/src/tool/mortgageExtraPaymentPlanner/component.astro +138 -0
- package/src/tool/mortgageExtraPaymentPlanner/controller.ts +150 -0
- package/src/tool/mortgageExtraPaymentPlanner/currency-defaults.ts +25 -0
- package/src/tool/mortgageExtraPaymentPlanner/dom-views.ts +161 -0
- package/src/tool/mortgageExtraPaymentPlanner/entry.ts +31 -0
- package/src/tool/mortgageExtraPaymentPlanner/evaluator.ts +24 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/de.ts +74 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/en.ts +185 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/es.ts +49 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/fr.ts +25 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/id.ts +18 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/it.ts +20 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/ja.ts +18 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/ko.ts +18 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/nl.ts +18 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/pl.ts +18 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/pt.ts +18 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/ru.ts +18 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/sv.ts +18 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/tr.ts +18 -0
- package/src/tool/mortgageExtraPaymentPlanner/i18n/zh.ts +18 -0
- package/src/tool/mortgageExtraPaymentPlanner/index.ts +11 -0
- package/src/tool/mortgageExtraPaymentPlanner/logic.test.ts +67 -0
- package/src/tool/mortgageExtraPaymentPlanner/logic.ts +263 -0
- package/src/tool/mortgageExtraPaymentPlanner/mortgage-amortization-extra-payment-planner.css +551 -0
- package/src/tool/mortgageExtraPaymentPlanner/seo.astro +14 -0
- package/src/tool/mortgageExtraPaymentPlanner/storage.ts +65 -0
- package/src/tool/mortgageExtraPaymentPlanner/ui.ts +48 -0
- package/src/tools.ts +3 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import type { MortgageInputs, MortgageResult, PaymentRow } from './logic';
|
|
2
|
+
import type { MortgageExtraPaymentPlannerUI } from './ui';
|
|
3
|
+
|
|
4
|
+
export interface MortgageViewContext {
|
|
5
|
+
result: MortgageResult;
|
|
6
|
+
inputs: MortgageInputs;
|
|
7
|
+
ui: MortgageExtraPaymentPlannerUI;
|
|
8
|
+
locale: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function money(value: number, currency: string, locale: string): string {
|
|
12
|
+
return new Intl.NumberFormat(locale, { style: 'currency', currency, maximumFractionDigits: 2 }).format(value);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function dateLabel(value: string, locale: string): string {
|
|
16
|
+
const date = new Date(`${value}T00:00:00Z`);
|
|
17
|
+
return new Intl.DateTimeFormat(locale, { dateStyle: 'medium', timeZone: 'UTC' }).format(date);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function textElement(tag: string, text: string, className?: string): HTMLElement {
|
|
21
|
+
const element = document.createElement(tag);
|
|
22
|
+
element.textContent = text;
|
|
23
|
+
if (className) element.className = className;
|
|
24
|
+
return element;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function createMetric(label: string, value: string, className: string): HTMLElement {
|
|
28
|
+
const element = document.createElement('div');
|
|
29
|
+
element.className = `mortgage-metric ${className}`;
|
|
30
|
+
element.append(textElement('span', label, 'mortgage-metric-label'), textElement('strong', value, 'mortgage-metric-value'));
|
|
31
|
+
return element;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function sampleRows(rows: PaymentRow[], count: number): PaymentRow[] {
|
|
35
|
+
if (rows.length <= count) return rows;
|
|
36
|
+
return Array.from({ length: count }, (_, index) => rows[Math.min(rows.length - 1, Math.round((index * (rows.length - 1)) / (count - 1)))])!;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function createPath(rows: PaymentRow[], principal: number): string {
|
|
40
|
+
return sampleRows(rows, 13).map((row, index, sampled) => {
|
|
41
|
+
const x = 42 + (index * 526) / Math.max(1, sampled.length - 1);
|
|
42
|
+
const y = 28 + (row.balance / principal) * 112;
|
|
43
|
+
return `${index === 0 ? 'M' : 'L'} ${x.toFixed(1)} ${y.toFixed(1)}`;
|
|
44
|
+
}).join(' ');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function addExtraMarkers(svg: SVGSVGElement, context: MortgageViewContext): void {
|
|
48
|
+
const sampled = sampleRows(context.result.schedule, 13);
|
|
49
|
+
sampled.forEach((row, index) => {
|
|
50
|
+
if (row.extra <= 0) return;
|
|
51
|
+
const marker = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
|
52
|
+
const x = 42 + (index * 526) / Math.max(1, sampled.length - 1);
|
|
53
|
+
marker.setAttribute('x1', x.toFixed(1));
|
|
54
|
+
marker.setAttribute('x2', x.toFixed(1));
|
|
55
|
+
marker.setAttribute('y1', '28');
|
|
56
|
+
marker.setAttribute('y2', '140');
|
|
57
|
+
marker.setAttribute('class', 'mortgage-extra-marker');
|
|
58
|
+
svg.append(marker);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function renderScene(container: HTMLElement, context: MortgageViewContext): void {
|
|
63
|
+
const { result, inputs, ui, locale } = context;
|
|
64
|
+
container.replaceChildren();
|
|
65
|
+
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
66
|
+
svg.setAttribute('viewBox', '0 0 620 180');
|
|
67
|
+
svg.setAttribute('role', 'img');
|
|
68
|
+
svg.setAttribute('aria-label', ui.balanceSceneLabel);
|
|
69
|
+
const baseline = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
70
|
+
baseline.setAttribute('d', createPath(result.baselineSchedule, inputs.principal));
|
|
71
|
+
baseline.setAttribute('class', 'mortgage-path mortgage-path-baseline');
|
|
72
|
+
const plan = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
73
|
+
plan.setAttribute('d', createPath(result.schedule, inputs.principal));
|
|
74
|
+
plan.setAttribute('class', 'mortgage-path mortgage-path-plan');
|
|
75
|
+
svg.append(baseline, plan);
|
|
76
|
+
addExtraMarkers(svg, context);
|
|
77
|
+
const legend = document.createElement('div');
|
|
78
|
+
legend.className = 'mortgage-scene-legend';
|
|
79
|
+
const baselineLegend = textElement('span', ui.baselineLabel, 'mortgage-legend-item mortgage-legend-baseline');
|
|
80
|
+
const planLegend = textElement('span', ui.planLabel, 'mortgage-legend-item mortgage-legend-plan');
|
|
81
|
+
legend.append(baselineLegend, planLegend);
|
|
82
|
+
const helper = textElement('p', ui.balanceSceneHelp, 'mortgage-scene-help');
|
|
83
|
+
const caption = textElement('p', `${ui.payoffDateLabel}: ${dateLabel(result.payoffDate, locale)}`, 'mortgage-scene-caption');
|
|
84
|
+
container.append(svg, legend, helper, caption);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function renderMetrics(container: HTMLElement, context: MortgageViewContext): void {
|
|
88
|
+
const { result, inputs, ui, locale } = context;
|
|
89
|
+
container.replaceChildren();
|
|
90
|
+
const currency = inputs.currency;
|
|
91
|
+
const converted = (value: number) => money(value, currency, locale);
|
|
92
|
+
const grid = document.createElement('div');
|
|
93
|
+
grid.className = 'mortgage-metrics';
|
|
94
|
+
grid.append(
|
|
95
|
+
createMetric(ui.regularPaymentLabel, converted(result.regularPayment), 'mortgage-metric-primary'),
|
|
96
|
+
createMetric(ui.interestSavedLabel, converted(result.interestSaved), 'mortgage-metric-positive'),
|
|
97
|
+
createMetric(ui.periodsSavedLabel, `${result.periodsSaved}`, 'mortgage-metric-positive'),
|
|
98
|
+
createMetric(ui.totalInterestLabel, converted(result.totalInterest), 'mortgage-metric-secondary'),
|
|
99
|
+
createMetric(ui.totalExtraLabel, converted(result.totalExtra), 'mortgage-metric-secondary'),
|
|
100
|
+
createMetric(ui.payoffDateLabel, dateLabel(result.payoffDate, locale), 'mortgage-metric-date'),
|
|
101
|
+
);
|
|
102
|
+
const status = textElement('p', `${ui.planLabel}: ${converted(result.interestSaved)} ${ui.interestSavedLabel.toLowerCase()}`, 'mortgage-result-note');
|
|
103
|
+
container.append(grid, status);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function addCell(row: HTMLTableRowElement, value: string, className?: string): void {
|
|
107
|
+
const cell = document.createElement('td');
|
|
108
|
+
cell.textContent = value;
|
|
109
|
+
if (className) cell.className = className;
|
|
110
|
+
row.append(cell);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function renderAnnualTable(container: HTMLElement, context: MortgageViewContext): void {
|
|
114
|
+
const { result, inputs, ui, locale } = context;
|
|
115
|
+
container.replaceChildren();
|
|
116
|
+
const currency = inputs.currency;
|
|
117
|
+
const converted = (value: number) => money(value, currency, locale);
|
|
118
|
+
const table = document.createElement('table');
|
|
119
|
+
table.className = 'mortgage-annual-table';
|
|
120
|
+
const head = document.createElement('thead');
|
|
121
|
+
const headRow = document.createElement('tr');
|
|
122
|
+
[ui.yearLabel, ui.paymentLabel, ui.interestLabel, ui.principalPaidLabel, ui.extraPaidLabel, ui.endingBalanceLabel].forEach((label) => {
|
|
123
|
+
headRow.append(textElement('th', label));
|
|
124
|
+
});
|
|
125
|
+
head.append(headRow);
|
|
126
|
+
const body = document.createElement('tbody');
|
|
127
|
+
result.annualSummary.forEach((summary) => {
|
|
128
|
+
const row = document.createElement('tr');
|
|
129
|
+
addCell(row, `${summary.year}`);
|
|
130
|
+
addCell(row, converted(summary.payment));
|
|
131
|
+
addCell(row, converted(summary.interest));
|
|
132
|
+
addCell(row, converted(summary.principal));
|
|
133
|
+
addCell(row, converted(summary.extra));
|
|
134
|
+
addCell(row, converted(summary.balance));
|
|
135
|
+
body.append(row);
|
|
136
|
+
});
|
|
137
|
+
table.append(head, body);
|
|
138
|
+
container.append(table);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function renderMortgageViews(
|
|
142
|
+
root: HTMLElement,
|
|
143
|
+
context: MortgageViewContext | null,
|
|
144
|
+
): void {
|
|
145
|
+
const scene = root.querySelector<HTMLElement>('[data-mortgage-scene]');
|
|
146
|
+
const metrics = root.querySelector<HTMLElement>('[data-mortgage-results]');
|
|
147
|
+
const annual = root.querySelector<HTMLElement>('[data-mortgage-annual]');
|
|
148
|
+
const empty = root.querySelector<HTMLElement>('[data-mortgage-empty]');
|
|
149
|
+
if (!scene || !metrics || !annual || !empty) return;
|
|
150
|
+
if (!context) {
|
|
151
|
+
scene.replaceChildren();
|
|
152
|
+
metrics.replaceChildren();
|
|
153
|
+
annual.replaceChildren();
|
|
154
|
+
empty.hidden = false;
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
empty.hidden = true;
|
|
158
|
+
renderScene(scene, context);
|
|
159
|
+
renderMetrics(metrics, context);
|
|
160
|
+
renderAnnualTable(annual, context);
|
|
161
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { FinanceToolEntry, ToolLocaleContent } from '../../types';
|
|
2
|
+
import type { MortgageExtraPaymentPlannerUI } from './ui';
|
|
3
|
+
|
|
4
|
+
export type MortgageExtraPaymentPlannerLocaleContent = ToolLocaleContent<MortgageExtraPaymentPlannerUI>;
|
|
5
|
+
|
|
6
|
+
export const mortgageExtraPaymentPlanner: FinanceToolEntry<MortgageExtraPaymentPlannerUI> = {
|
|
7
|
+
id: 'mortgage-extra-payment-planner',
|
|
8
|
+
icons: {
|
|
9
|
+
bg: 'mdi:home-currency-usd',
|
|
10
|
+
fg: 'mdi:chart-timeline-variant',
|
|
11
|
+
},
|
|
12
|
+
i18n: {
|
|
13
|
+
en: () => import('./i18n/en').then((m) => m.content),
|
|
14
|
+
de: () => import('./i18n/de').then((m) => m.content),
|
|
15
|
+
es: () => import('./i18n/es').then((m) => m.content),
|
|
16
|
+
fr: () => import('./i18n/fr').then((m) => m.content),
|
|
17
|
+
id: () => import('./i18n/id').then((m) => m.content),
|
|
18
|
+
it: () => import('./i18n/it').then((m) => m.content),
|
|
19
|
+
ja: () => import('./i18n/ja').then((m) => m.content),
|
|
20
|
+
ko: () => import('./i18n/ko').then((m) => m.content),
|
|
21
|
+
nl: () => import('./i18n/nl').then((m) => m.content),
|
|
22
|
+
pl: () => import('./i18n/pl').then((m) => m.content),
|
|
23
|
+
pt: () => import('./i18n/pt').then((m) => m.content),
|
|
24
|
+
ru: () => import('./i18n/ru').then((m) => m.content),
|
|
25
|
+
sv: () => import('./i18n/sv').then((m) => m.content),
|
|
26
|
+
tr: () => import('./i18n/tr').then((m) => m.content),
|
|
27
|
+
zh: () => import('./i18n/zh').then((m) => m.content),
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export { bibliography } from './bibliography';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { MortgageExtraPaymentPlannerUI } from './ui';
|
|
2
|
+
import type { MortgageInputs, MortgageResult } from './logic';
|
|
3
|
+
|
|
4
|
+
export interface MortgageEvaluation {
|
|
5
|
+
badge: string;
|
|
6
|
+
message: string;
|
|
7
|
+
tone: 'neutral' | 'positive' | 'warning';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function evaluateMortgage(
|
|
11
|
+
inputs: MortgageInputs,
|
|
12
|
+
result: MortgageResult | null,
|
|
13
|
+
ui: MortgageExtraPaymentPlannerUI,
|
|
14
|
+
): MortgageEvaluation {
|
|
15
|
+
if (!result) return { badge: ui.invalidInputMessage, message: ui.emptyMessage, tone: 'warning' };
|
|
16
|
+
if (result.periodsSaved > 0) {
|
|
17
|
+
return {
|
|
18
|
+
badge: `${result.periodsSaved} ${ui.periodsSavedLabel.toLowerCase()}`,
|
|
19
|
+
message: `${ui.planLabel}: ${result.interestSaved.toFixed(2)} ${inputs.currency} ${ui.interestSavedLabel.toLowerCase()}`,
|
|
20
|
+
tone: 'positive',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return { badge: ui.baselineLabel, message: ui.currencyHelp, tone: 'neutral' };
|
|
24
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography';
|
|
2
|
+
import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
|
|
3
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
4
|
+
import type { MortgageExtraPaymentPlannerUI } from '../ui';
|
|
5
|
+
|
|
6
|
+
const slug = 'hypotheken-amortisationsrechner-sondertilgung';
|
|
7
|
+
const title = 'Hypothekenrechner mit Sondertilgungen';
|
|
8
|
+
const description = 'Plane eine Hypothek mit festem Zinssatz und regelmäßigen oder einmaligen Sondertilgungen, vergleiche die gesparten Zinsen und zeige alle Beträge in einer Währung an.';
|
|
9
|
+
|
|
10
|
+
const ui: MortgageExtraPaymentPlannerUI = {
|
|
11
|
+
currencyLabel: 'Währung', currencyHelp: 'Einmal auswählen. Jeder Betrag im Plan verwendet diese Währung.',
|
|
12
|
+
principalLabel: 'Anfangsschuld', principalHelp: 'Noch geschuldeter Betrag zu Beginn dieses Plans',
|
|
13
|
+
annualRateLabel: 'Jährlicher Zinssatz', annualRateHelp: 'Nominaler fester Zinssatz für jede Zahlungsperiode',
|
|
14
|
+
termLabel: 'Verbleibende Laufzeit in Jahren', termHelp: 'Geplante Laufzeit ohne Sondertilgungen',
|
|
15
|
+
frequencyLabel: 'Zahlungsrhythmus', recurringExtraLabel: 'Regelmäßige Sondertilgung', recurringExtraHelp: 'Zusätzlicher Tilgungsbetrag pro Periode',
|
|
16
|
+
oneOffExtraLabel: 'Einmalige Sondertilgung', oneOffExtraHelp: 'Eine einzelne Tilgung in der unten gewählten Periode',
|
|
17
|
+
oneOffPeriodLabel: 'Periode der Einmalzahlung', oneOffPeriodHelp: '1 bedeutet die erste Zahlungsperiode',
|
|
18
|
+
startDateLabel: 'Erster Zahlungstermin', startDateHelp: 'Wird zur Schätzung des Rückzahlungstermins verwendet',
|
|
19
|
+
extraSectionTitle: 'Sondertilgungsplan', outputTitle: 'Schuldenverlauf', regularPaymentLabel: 'Regelmäßige Zahlung ohne Extras',
|
|
20
|
+
interestSavedLabel: 'Gesparte Zinsen', periodsSavedLabel: 'Perioden gespart', payoffDateLabel: 'Geschätzte Rückzahlung',
|
|
21
|
+
totalInterestLabel: 'Gezahlte Zinsen mit diesem Plan', totalExtraLabel: 'Zusätzliche Tilgung', baselineLabel: 'Ursprünglicher Plan', planLabel: 'Mit deinen Sondertilgungen',
|
|
22
|
+
balanceSceneLabel: 'Ursprüngliche Restschuld im Vergleich zur Restschuld nach Sondertilgungen', balanceSceneHelp: 'Die gestrichelte Linie zeigt den ursprünglichen Plan. Die kupferfarbene Linie zeigt deinen Plan. Grüne Markierungen zeigen zusätzliche Tilgung.',
|
|
23
|
+
annualScheduleTitle: 'Jährlicher Zahlungsplan', yearLabel: 'Jahr', paymentLabel: 'Gesamtzahlung', interestLabel: 'Zinsen', principalPaidLabel: 'Planmäßige Tilgung', extraPaidLabel: 'Zusätzliche Tilgung', endingBalanceLabel: 'Restschuld',
|
|
24
|
+
formulaTitle: 'Modell und Grenzen', formulaText: 'Der Rechner verwendet ein Amortisationsmodell mit festem Zinssatz. In jeder Periode werden Zinsen auf die Eröffnungsschuld berechnet, die reguläre Zahlung auf Zinsen und Tilgung verteilt und danach regelmäßige sowie einmalige Sondertilgungen angewendet. Der jährliche Zinssatz wird durch die Zahl der Perioden geteilt. Die letzte Zahlung wird reduziert, wenn die Restschuld kleiner als die geplante Zahlung ist. Beim Wechsel der Währung werden die Geldbeträge mit einem internen Planungsfaktor umgerechnet und dasselbe Szenario neu berechnet.',
|
|
25
|
+
riskNote: 'Dies ist eine Schätzung, keine Abrechnung des Kreditgebers. Der Währungswähler verwendet interne Planungsfaktoren, keine Live-Wechselkurse. Variable Zinsen, Gebühren, Versicherungen, Steuern, Zahlungspausen, Tageszinsen, Entschädigungen und Vertragsregeln zur Sondertilgung sind nicht enthalten.',
|
|
26
|
+
emptyMessage: 'Gib eine gültige Schuld, einen Zinssatz, eine Laufzeit und ein Datum ein, um den Plan zu sehen.', invalidInputMessage: 'Prüfe die Eingaben, um den Plan zu sehen',
|
|
27
|
+
currencyOptions: { AUD: 'A$ AUD · Australischer Dollar', BRL: 'R$ BRL · Brasilianischer Real', CAD: 'C$ CAD · Kanadischer Dollar', CHF: 'CHF · Schweizer Franken', CNY: '¥ CNY · Chinesischer Yuan', CZK: 'Kč CZK · Tschechische Krone', DKK: 'kr DKK · Dänische Krone', EUR: '€ EUR · Euro', GBP: '£ GBP · Britisches Pfund', IDR: 'Rp IDR · Indonesische Rupiah', INR: '₹ INR · Indische Rupie', JPY: '¥ JPY · Japanischer Yen', KRW: '₩ KRW · Südkoreanischer Won', MXN: 'MX$ MXN · Mexikanischer Peso', NOK: 'kr NOK · Norwegische Krone', PLN: 'zł PLN · Polnischer Zloty', RUB: '₽ RUB · Russischer Rubel', SEK: 'kr SEK · Schwedische Krone', TRY: '₺ TRY · Türkische Lira', USD: '$ USD · US-Dollar' },
|
|
28
|
+
currencySymbols: { AUD: 'A$', BRL: 'R$', CAD: 'C$', CHF: 'CHF', CNY: '¥', CZK: 'Kč', DKK: 'kr', EUR: '€', GBP: '£', IDR: 'Rp', INR: '₹', JPY: '¥', KRW: '₩', MXN: 'MX$', NOK: 'kr', PLN: 'zł', RUB: '₽', SEK: 'kr', TRY: '₺', USD: '$' },
|
|
29
|
+
frequencyOptions: { monthly: 'Monatlich', biweekly: 'Alle zwei Wochen', weekly: 'Wöchentlich' },
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const faq = [
|
|
33
|
+
{ question: 'Wie verändern zusätzliche Hypothekenzahlungen den Plan?', answer: 'Der Rechner lässt die reguläre Zahlung unverändert und wendet deine zusätzliche Tilgung nach jeder planmäßigen Zahlung an. Die Schuld kann dadurch früher auf null sinken und die Gesamtzinsen können fallen. Dein Kreditgeber kann Sondertilgungen anders behandeln, daher vergleiche das Ergebnis mit dem Vertrag.' },
|
|
34
|
+
{ question: 'Was passiert beim Wechsel der Währung?', answer: 'Der Rechner rechnet die Geldbeträge mit einem internen Planungsfaktor in die neue Währung um und berechnet dasselbe Szenario neu. Der Faktor ist kein Live-Kurs; nutze das Ergebnis zur Planung, nicht als aktuelle Wechselkursangabe.' },
|
|
35
|
+
{ question: 'Warum gibt es nur einen Währungswähler?', answer: 'Die ausgewählte Währung gilt für Schuld, Sondertilgungen, reguläre Zahlungen, Zinsen, Restschulden und die Jahrestabelle. Eine gemeinsame Einheit hält das Formular verständlich und verhindert vermischte Währungen.' },
|
|
36
|
+
{ question: 'Berechnet der Rechner meine echte Kreditrate?', answer: 'Er schätzt einen Amortisationsplan mit festem Zinssatz. Vertragsregeln, Zinstage, Gebühren, Versicherungen, Steuern, Zinsänderungen, Entschädigungen und die genaue Behandlung vorzeitiger Tilgung sind nicht bekannt. Für den vertraglichen Betrag zählen Abrechnung und Vertrag.' },
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
const howTo = [
|
|
40
|
+
{ name: 'Währung festlegen', text: 'Wähle die eine Währung, die du verwenden möchtest. Sie gilt für alle Geldbeträge und Ergebnisse.' },
|
|
41
|
+
{ name: 'Kredit beschreiben', text: 'Gib Anfangsschuld, nominalen Jahreszins, Restlaufzeit, ersten Zahlungstermin und Zahlungsrhythmus ein.' },
|
|
42
|
+
{ name: 'Sondertilgungen hinzufügen', text: 'Trage einen Betrag pro Periode ein und ergänze optional eine Einmalzahlung mit ihrer Periode.' },
|
|
43
|
+
{ name: 'Vergleich lesen', text: 'Vergleiche die ursprüngliche Restschuld mit deinem Plan und prüfe gesparte Zinsen, gesparte Perioden, Rückzahlungstermin und Jahrestabelle.' },
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
const faqSchema: WithContext<FAQPage> = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
|
|
47
|
+
const howToSchema: WithContext<HowTo> = { '@context': 'https://schema.org', '@type': 'HowTo', name: title, description, step: howTo.map((step, index) => ({ '@type': 'HowToStep', position: index + 1, name: step.name, text: step.text })) };
|
|
48
|
+
const appSchema: WithContext<SoftwareApplication> = { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: title, description, applicationCategory: 'FinanceApplication', operatingSystem: 'All', offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' }, inLanguage: 'de' };
|
|
49
|
+
|
|
50
|
+
export const content: ToolLocaleContent<MortgageExtraPaymentPlannerUI> = {
|
|
51
|
+
slug, title, description, ui, faq, bibliography, howTo, schemas: [appSchema, faqSchema, howToSchema],
|
|
52
|
+
seo: [
|
|
53
|
+
{ type: 'title', text: 'Plane, was Sondertilgungen an deiner Hypothek ändern', level: 2 },
|
|
54
|
+
{ type: 'paragraph', html: '<p>Ein Tilgungsplan trennt jede Zahlung in Zinsen und Tilgung. Wenn du zusätzliche Tilgung leistest und die reguläre Zahlung gleich bleibt, kann die Restschuld früher auf null sinken. Dieser Rechner macht den Unterschied zwischen ursprünglichem Verlauf und deinem Plan sichtbar.</p>' },
|
|
55
|
+
{ type: 'paragraph', html: '<p>Das Ergebnis ist eine Schätzung für ein Darlehen mit festem Zinssatz. Es berücksichtigt Schuld, nominalen Jahreszins, Zahlungsperioden und den nach jeder Zahlung sinkenden Saldo. Vertragsregeln, Rundungen und Gebühren können beim Kreditgeber anders sein.</p>' },
|
|
56
|
+
{ type: 'title', text: 'So funktioniert die Amortisationsrechnung', level: 3 },
|
|
57
|
+
{ type: 'paragraph', html: '<p>In jeder Periode werden die Zinsen aus der Eröffnungsschuld berechnet. Der Jahreszins wird durch die Zahl der Perioden geteilt. Danach wird die reguläre Zahlung auf Zinsen und Tilgung verteilt; regelmäßige und einmalige Sondertilgungen senken die Restschuld zusätzlich.</p>' },
|
|
58
|
+
{ type: 'table', headers: ['Wert', 'Berechnung', 'Bedeutung'], rows: [['Periodischer Zins', 'Jahreszins / Perioden pro Jahr', 'Zins für eine Zahlungsperiode'], ['Reguläre Zahlung', 'Feste Zahlungsformel', 'Zahlung vor zusätzlicher Tilgung'], ['Periodenzins', 'Eröffnungsschuld x periodischer Zins', 'Vom Modell angenommener Zins'], ['Restschuld', 'Eröffnungsschuld - Tilgung - Extras', 'Im Plan noch geschuldeter Betrag']] },
|
|
59
|
+
{ type: 'title', text: 'Was Sondertilgungen tatsächlich ändern', level: 3 },
|
|
60
|
+
{ type: 'paragraph', html: '<p>Eine Sondertilgung senkt in diesem Modell direkt die Schuld. Künftige Zinsen werden deshalb auf einen kleineren Betrag berechnet. Sieh dir sowohl gesparte Zinsen als auch gesparte Perioden an: Der erste Wert beschreibt vermiedene Finanzierungskosten, der zweite den früheren Rückzahlungstermin.</p>' },
|
|
61
|
+
{ type: 'paragraph', html: '<p>Der Kreditgeber kann stattdessen die reguläre Rate senken, die Laufzeit beibehalten oder eine formelle Anfrage verlangen. Prüfe daher Grenzen, Mindestbeträge und mögliche Entschädigungen vor einer Zahlung.</p>' },
|
|
62
|
+
{ type: 'title', text: 'Währungen einfach und ohne Mischrechnung verwenden', level: 3 },
|
|
63
|
+
{ type: 'paragraph', html: '<p>Wähle eine Währung für den Haushaltsplan oder die Kreditabrechnung. Sie gilt für Schuld, Sondertilgungen, Zahlungen, Zinsen und Restschulden. Beim Wechsel werden die Geldbeträge intern umgerechnet, die Struktur des Szenarios bleibt gleich.</p>' },
|
|
64
|
+
{ type: 'list', items: ['Wähle die Währung deines Budgets oder der Kreditabrechnung.', 'Gib Schuld und jede Sondertilgung in der ausgewählten Einheit ein.', 'Behandle den Wechsel als neue Planungseinheit, nicht als Änderung des Kreditvertrags.', 'Prüfe den zulässigen Zahlungsrhythmus und die Regeln für vorzeitige Tilgung.', 'Nutze die Jahrestabelle, um die Wirkung einer Einmalzahlung zu erkennen.'] },
|
|
65
|
+
{ type: 'title', text: 'Ein einfaches Beispiel für die Ausgabe', level: 3 },
|
|
66
|
+
{ type: 'paragraph', html: '<p>Bei 250.000 EUR, 3,5 Prozent festem Jahreszins und 25 Jahren Restlaufzeit verändern 150 EUR monatliche Sondertilgung sowie 5.000 EUR in Periode 12 die ursprüngliche reguläre Zahlung in diesem Modell nicht. Sie senken aber die Restschuld und damit spätere Zinsen.</p>' },
|
|
67
|
+
{ type: 'paragraph', html: '<p>Wenn du zu USD wechselst, rechnet der Rechner die Beträge mit dem internen Planungsfaktor um und berechnet dasselbe Szenario neu. Das ist eine übersichtliche Planungshilfe, aber keine aktuelle Markt- oder Vertragsbewertung.</p>' },
|
|
68
|
+
{ type: 'title', text: 'Vor einer Entscheidung prüfen', level: 3 },
|
|
69
|
+
{ type: 'list', items: ['Frage, ob eine Sondertilgung Laufzeit oder Rate reduziert.', 'Prüfe jährliche Grenzen, Mindestbeträge und Entschädigungen.', 'Bestätige, ob der genannte Zins nominal, effektiv, fest oder variabel ist.', 'Vergleiche den Saldo mit einer aktuellen Abrechnung des Kreditgebers.', 'Notiere bei internationaler Planung den verwendeten Wechselkurs und das Datum.'] },
|
|
70
|
+
{ type: 'tip', title: 'Die Grafik ist ein Vergleich, kein Versprechen', html: '<p>Die gestrichelte Linie zeigt den ursprünglichen festen Plan ohne Extras. Die kupferfarbene Linie folgt deinen Eingaben. Gebühren, Versicherungen, Steuern, tägliche Zinsen, Wechselkursbewegungen und Vertragsregeln sind nicht enthalten.</p>' },
|
|
71
|
+
{ type: 'title', text: 'Grenzen dieses Hypothekenrechners', level: 3 },
|
|
72
|
+
{ type: 'paragraph', html: '<p>Das Werkzeug modelliert ein vollständig tilgendes Darlehen mit festem Zinssatz, regelmäßigen Zahlungen und optionaler zusätzlicher Tilgung. Es hilft bei Szenarien und Fragen an den Kreditgeber. Es beurteilt keine Tragbarkeit, erteilt keine Steuer- oder Rechtsberatung und ersetzt keine Abrechnung.</p>' },
|
|
73
|
+
],
|
|
74
|
+
};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography';
|
|
2
|
+
import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
|
|
3
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
4
|
+
import type { MortgageExtraPaymentPlannerUI } from '../ui';
|
|
5
|
+
|
|
6
|
+
const slug = 'mortgage-amortization-extra-payment-planner';
|
|
7
|
+
const title = 'Mortgage Amortization Planner with Extra Payments';
|
|
8
|
+
const description = 'Plan a fixed rate mortgage with recurring or one off extra payments, compare interest saved and view every amount in one chosen currency.';
|
|
9
|
+
|
|
10
|
+
const ui: MortgageExtraPaymentPlannerUI = {
|
|
11
|
+
currencyLabel: 'Currency',
|
|
12
|
+
currencyHelp: 'Choose once. Every amount in the plan uses this currency.',
|
|
13
|
+
principalLabel: 'Starting principal',
|
|
14
|
+
principalHelp: 'The amount still owed at the start of this plan',
|
|
15
|
+
annualRateLabel: 'Annual interest rate',
|
|
16
|
+
annualRateHelp: 'Nominal fixed rate used for each payment period',
|
|
17
|
+
termLabel: 'Remaining term in years',
|
|
18
|
+
termHelp: 'The planned duration before extra payments',
|
|
19
|
+
frequencyLabel: 'Payment frequency',
|
|
20
|
+
recurringExtraLabel: 'Recurring extra payment',
|
|
21
|
+
recurringExtraHelp: 'Additional principal paid every period',
|
|
22
|
+
oneOffExtraLabel: 'One off extra payment',
|
|
23
|
+
oneOffExtraHelp: 'A single principal payment in the period below',
|
|
24
|
+
oneOffPeriodLabel: 'One off payment period',
|
|
25
|
+
oneOffPeriodHelp: '1 means the first payment period',
|
|
26
|
+
startDateLabel: 'First payment date',
|
|
27
|
+
startDateHelp: 'Used to estimate the payoff date',
|
|
28
|
+
extraSectionTitle: 'Extra payment plan',
|
|
29
|
+
outputTitle: 'Balance path',
|
|
30
|
+
regularPaymentLabel: 'Regular payment before extras',
|
|
31
|
+
interestSavedLabel: 'Interest saved',
|
|
32
|
+
periodsSavedLabel: 'periods saved',
|
|
33
|
+
payoffDateLabel: 'Estimated payoff',
|
|
34
|
+
totalInterestLabel: 'Interest paid with this plan',
|
|
35
|
+
totalExtraLabel: 'Extra principal paid',
|
|
36
|
+
baselineLabel: 'Original schedule',
|
|
37
|
+
planLabel: 'With your extra payments',
|
|
38
|
+
balanceSceneLabel: 'Original mortgage balance compared with the balance after extra payments',
|
|
39
|
+
balanceSceneHelp: 'The dashed line is the original schedule. The copper line is your plan. Green marks show periods with extra principal.',
|
|
40
|
+
annualScheduleTitle: 'Annual payment schedule',
|
|
41
|
+
yearLabel: 'Year',
|
|
42
|
+
paymentLabel: 'Total paid',
|
|
43
|
+
interestLabel: 'Interest',
|
|
44
|
+
principalPaidLabel: 'Scheduled principal',
|
|
45
|
+
extraPaidLabel: 'Extra principal',
|
|
46
|
+
endingBalanceLabel: 'Ending balance',
|
|
47
|
+
formulaTitle: 'Model and limits',
|
|
48
|
+
formulaText: 'The planner uses a fixed rate amortization model. Each period calculates interest on the opening balance, applies the regular payment to interest and principal, then applies recurring and one off extra principal. Interest is annual rate divided by the number of periods per year. The final payment is reduced when the remaining balance is smaller than the planned payment. Changing the currency converts the monetary inputs with an internal planning ratio before calculating the same scenario again.',
|
|
49
|
+
riskNote: 'This is an estimate, not a lender statement. The currency selector uses internal planning ratios, not live market rates. The model does not include variable rates, fees, insurance, taxes, payment holidays, daily interest, penalties or the contract rules that determine how your lender applies an overpayment.',
|
|
50
|
+
emptyMessage: 'Enter a valid principal, rate, term and date to see the plan.',
|
|
51
|
+
invalidInputMessage: 'Check the inputs to see the plan',
|
|
52
|
+
currencyOptions: {
|
|
53
|
+
AUD: 'A$ AUD · Australian dollar',
|
|
54
|
+
BRL: 'R$ BRL · Brazilian real',
|
|
55
|
+
CAD: 'C$ CAD · Canadian dollar',
|
|
56
|
+
CHF: 'CHF · Swiss franc',
|
|
57
|
+
CNY: '¥ CNY · Chinese yuan',
|
|
58
|
+
CZK: 'Kč CZK · Czech koruna',
|
|
59
|
+
DKK: 'kr DKK · Danish krone',
|
|
60
|
+
EUR: '€ EUR · Euro',
|
|
61
|
+
GBP: '£ GBP · Pound sterling',
|
|
62
|
+
IDR: 'Rp IDR · Indonesian rupiah',
|
|
63
|
+
INR: '₹ INR · Indian rupee',
|
|
64
|
+
JPY: '¥ JPY · Japanese yen',
|
|
65
|
+
KRW: '₩ KRW · South Korean won',
|
|
66
|
+
MXN: 'MX$ MXN · Mexican peso',
|
|
67
|
+
NOK: 'kr NOK · Norwegian krone',
|
|
68
|
+
PLN: 'zł PLN · Polish zloty',
|
|
69
|
+
RUB: '₽ RUB · Russian ruble',
|
|
70
|
+
SEK: 'kr SEK · Swedish krona',
|
|
71
|
+
TRY: '₺ TRY · Turkish lira',
|
|
72
|
+
USD: '$ USD · US dollar',
|
|
73
|
+
},
|
|
74
|
+
currencySymbols: {
|
|
75
|
+
AUD: 'A$',
|
|
76
|
+
BRL: 'R$',
|
|
77
|
+
CAD: 'C$',
|
|
78
|
+
CHF: 'CHF',
|
|
79
|
+
CNY: '¥',
|
|
80
|
+
CZK: 'Kč',
|
|
81
|
+
DKK: 'kr',
|
|
82
|
+
EUR: '€',
|
|
83
|
+
GBP: '£',
|
|
84
|
+
IDR: 'Rp',
|
|
85
|
+
INR: '₹',
|
|
86
|
+
JPY: '¥',
|
|
87
|
+
KRW: '₩',
|
|
88
|
+
MXN: 'MX$',
|
|
89
|
+
NOK: 'kr',
|
|
90
|
+
PLN: 'zł',
|
|
91
|
+
RUB: '₽',
|
|
92
|
+
SEK: 'kr',
|
|
93
|
+
TRY: '₺',
|
|
94
|
+
USD: '$',
|
|
95
|
+
},
|
|
96
|
+
frequencyOptions: {
|
|
97
|
+
monthly: 'Monthly',
|
|
98
|
+
biweekly: 'Every two weeks',
|
|
99
|
+
weekly: 'Weekly',
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const faq = [
|
|
104
|
+
{
|
|
105
|
+
question: 'How do extra mortgage payments change the schedule?',
|
|
106
|
+
answer: 'This planner keeps the regular payment unchanged and applies your extra principal after each scheduled payment. The balance can therefore reach zero earlier and the interest total can fall. Your lender may apply an overpayment differently, so compare the result with your contract.',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
question: 'What happens when I change the currency?',
|
|
110
|
+
answer: 'The planner converts the monetary inputs to the new currency with an internal planning ratio, then recalculates the same scenario. The ratio is not a live market quote, so use the result for planning rather than as a current exchange-rate statement.',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
question: 'Why is there only one currency selector?',
|
|
114
|
+
answer: 'The selected currency applies to the principal, extra payments, regular payments, interest, balances and annual schedule. One shared unit keeps the form readable and prevents accidentally mixing currencies inside one calculation.',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
question: 'Does the planner calculate my real lender payment?',
|
|
118
|
+
answer: 'It estimates a fixed rate amortization schedule. It does not know your lender contract, day count convention, fees, insurance, taxes, rate revisions, penalties or the exact treatment of an early repayment. Use your statement and contract for the contractual figure.',
|
|
119
|
+
},
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
const howTo = [
|
|
123
|
+
{ name: 'Set the currency', text: 'Choose the single currency you want to use. The planner applies it to every monetary input and result.' },
|
|
124
|
+
{ name: 'Describe the loan', text: 'Enter the principal, nominal annual rate, remaining term, first payment date and payment frequency.' },
|
|
125
|
+
{ name: 'Add extra payments', text: 'Enter an extra amount paid every period, then add one optional lump sum and the period when it happens.' },
|
|
126
|
+
{ name: 'Read the comparison', text: 'Compare the dashed original balance with your plan, then review interest saved, periods saved, payoff date and the annual schedule.' },
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
130
|
+
'@context': 'https://schema.org',
|
|
131
|
+
'@type': 'FAQPage',
|
|
132
|
+
mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })),
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const howToSchema: WithContext<HowTo> = {
|
|
136
|
+
'@context': 'https://schema.org',
|
|
137
|
+
'@type': 'HowTo',
|
|
138
|
+
name: title,
|
|
139
|
+
description,
|
|
140
|
+
step: howTo.map((step, index) => ({ '@type': 'HowToStep', position: index + 1, name: step.name, text: step.text })),
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
144
|
+
'@context': 'https://schema.org',
|
|
145
|
+
'@type': 'SoftwareApplication',
|
|
146
|
+
name: title,
|
|
147
|
+
description,
|
|
148
|
+
applicationCategory: 'FinanceApplication',
|
|
149
|
+
operatingSystem: 'All',
|
|
150
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
|
|
151
|
+
inLanguage: 'en',
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export const content: ToolLocaleContent<MortgageExtraPaymentPlannerUI> = {
|
|
155
|
+
slug,
|
|
156
|
+
title,
|
|
157
|
+
description,
|
|
158
|
+
ui,
|
|
159
|
+
faq,
|
|
160
|
+
bibliography,
|
|
161
|
+
howTo,
|
|
162
|
+
schemas: [appSchema, faqSchema, howToSchema],
|
|
163
|
+
seo: [
|
|
164
|
+
{ type: 'title', text: 'Plan what extra mortgage payments can change', level: 2 },
|
|
165
|
+
{ type: 'paragraph', html: '<p>An amortization schedule separates each payment into interest and principal. When you pay extra principal and the lender keeps the regular payment unchanged, the balance can reach zero sooner. This planner makes that tradeoff visible by comparing the original balance path with the path created by your recurring and one off extra payments.</p>' },
|
|
166
|
+
{ type: 'paragraph', html: '<p>The result is a planning estimate for a fixed rate loan. It uses the principal, nominal annual rate, number of payment periods, and an opening balance that changes after each payment. It does not promise the exact amount your lender will charge because contracts can use different day counts, fees, rounding rules, or overpayment instructions.</p>' },
|
|
167
|
+
{ type: 'title', text: 'How the amortization calculation works', level: 3 },
|
|
168
|
+
{ type: 'paragraph', html: '<p>For each period, the model calculates interest from the opening balance. The periodic rate is the annual rate divided by the number of periods per year. The regular payment is then found with the fixed payment formula. After the scheduled principal, the recurring extra and the selected one off payment reduce the balance further.</p>' },
|
|
169
|
+
{ type: 'table', headers: ['Figure', 'Calculation', 'Interpretation'], rows: [['Periodic rate', 'Annual rate / periods per year', 'The rate applied in each payment period'], ['Regular payment', 'Principal x rate x (1 + rate)^n / ((1 + rate)^n - 1)', 'The fixed payment before extra principal'], ['Interest in a period', 'Opening balance x periodic rate', 'The interest implied by the model for that period'], ['Balance after payment', 'Opening balance - scheduled principal - extra principal', 'The amount still owed in the plan']] },
|
|
170
|
+
{ type: 'title', text: 'What extra payments actually change', level: 3 },
|
|
171
|
+
{ type: 'paragraph', html: '<p>An extra payment is applied to principal in this model, so future interest is calculated on a smaller balance. The useful comparison is not only the amount of extra cash paid. Look at both interest saved and periods saved: one shows the financing cost avoided, while the other shows how much earlier the model reaches zero.</p>' },
|
|
172
|
+
{ type: 'paragraph', html: '<p>The lender may instead reduce the regular payment, keep the term, or require a formal request before changing the schedule. Some contracts also impose limits or compensation for early repayment. Use this output to prepare a question for the lender, not to replace the lender statement.</p>' },
|
|
173
|
+
{ type: 'title', text: 'Use currencies without mixing the math', level: 3 },
|
|
174
|
+
{ type: 'paragraph', html: '<p>Choose one currency before entering the loan amounts. The selector applies to the principal, recurring extra, lump sum, payments, interest and balances, so the form never asks you to reconcile two currency columns. Switching currency converts the monetary inputs internally and keeps the scenario structure intact.</p>' },
|
|
175
|
+
{ type: 'list', items: ['Choose the currency you use for the household budget or lender statement.', 'Keep the principal and every extra payment in the selected currency.', 'Treat a currency switch as a planning-unit change, not as a change to the lender contract.', 'Check whether your lender permits the selected frequency and how it applies early principal.', 'Review the annual table to find the years in which the lump sum makes the largest difference.'] },
|
|
176
|
+
{ type: 'title', text: 'A simple example to interpret the output', level: 3 },
|
|
177
|
+
{ type: 'paragraph', html: '<p>Suppose the starting principal is 250,000 EUR at a fixed nominal rate of 3.5% over 25 years. A recurring extra of 150 EUR and a 5,000 EUR lump sum in period 12 do not change the original regular payment in this model. They do lower the balance after the relevant periods, which reduces later interest and moves the estimated payoff date earlier.</p>' },
|
|
178
|
+
{ type: 'paragraph', html: '<p>If you switch the currency to USD, the tool converts the monetary inputs with its internal planning ratio and recalculates the same loan scenario in dollars. That keeps the interface simple, but the result is not a live market valuation and should not replace a lender statement or current FX quote.</p>' },
|
|
179
|
+
{ type: 'title', text: 'What to check before acting', level: 3 },
|
|
180
|
+
{ type: 'list', items: ['Ask the lender whether an overpayment reduces the term or the regular payment.', 'Check any early repayment compensation, annual limits and minimum lump sum.', 'Confirm whether the stated rate is nominal, effective, fixed, variable or subject to a review.', 'Compare the calculated balance with a recent lender statement before making a payment.', 'Save the exchange rate and date if the result is part of an international household budget.'] },
|
|
181
|
+
{ type: 'tip', title: 'The chart is a comparison, not a promise', html: '<p>The dashed line assumes the original fixed schedule without extra payments. The copper line follows the inputs you entered. Neither line includes contract specific fees, insurance, taxes, variable rate changes, daily interest, currency market movements or a guarantee that the lender will apply an overpayment in the same way.</p>' },
|
|
182
|
+
{ type: 'title', text: 'Limits of this mortgage planner', level: 3 },
|
|
183
|
+
{ type: 'paragraph', html: '<p>This tool models a fully amortizing fixed rate loan with regular payments and optional extra principal. It is useful for exploring scenarios and preparing questions. It cannot determine affordability, approve a loan, provide tax or legal advice, forecast exchange rates, reproduce a lender statement, or establish which early repayment rules apply in your country.</p>' },
|
|
184
|
+
],
|
|
185
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography';
|
|
2
|
+
import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
|
|
3
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
4
|
+
import type { MortgageExtraPaymentPlannerUI } from '../ui';
|
|
5
|
+
|
|
6
|
+
const slug = 'calculadora-amortizacion-hipoteca-pagos-extra';
|
|
7
|
+
const title = 'Calculadora de amortización hipotecaria con pagos extra';
|
|
8
|
+
const description = 'Planifica una hipoteca a tipo fijo con pagos extra periódicos o puntuales, compara los intereses ahorrados y muestra todos los importes en una sola moneda.';
|
|
9
|
+
const ui: MortgageExtraPaymentPlannerUI = {
|
|
10
|
+
currencyLabel: 'Moneda', currencyHelp: 'Elige una vez. Todos los importes del plan usarán esta moneda.', principalLabel: 'Capital pendiente inicial', principalHelp: 'Importe que queda por pagar al comenzar este plan', annualRateLabel: 'Tipo de interés anual', annualRateHelp: 'Tipo nominal fijo aplicado en cada periodo de pago', termLabel: 'Plazo restante en años', termHelp: 'Duración prevista antes de los pagos extra', frequencyLabel: 'Frecuencia de pago', recurringExtraLabel: 'Pago extra periódico', recurringExtraHelp: 'Capital adicional pagado en cada periodo', oneOffExtraLabel: 'Pago extra puntual', oneOffExtraHelp: 'Un pago único de capital en el periodo indicado', oneOffPeriodLabel: 'Periodo del pago puntual', oneOffPeriodHelp: '1 significa el primer periodo de pago', startDateLabel: 'Fecha del primer pago', startDateHelp: 'Se usa para estimar la fecha de liquidación', extraSectionTitle: 'Plan de pagos extra', outputTitle: 'Evolución del saldo', regularPaymentLabel: 'Cuota normal antes de extras', interestSavedLabel: 'Intereses ahorrados', periodsSavedLabel: 'periodos ahorrados', payoffDateLabel: 'Liquidación estimada', totalInterestLabel: 'Intereses pagados con este plan', totalExtraLabel: 'Capital extra pagado', baselineLabel: 'Calendario original', planLabel: 'Con tus pagos extra', balanceSceneLabel: 'Saldo hipotecario original frente al saldo después de los pagos extra', balanceSceneHelp: 'La línea discontinua es el calendario original. La línea cobre es tu plan. Las marcas verdes señalan periodos con capital extra.', annualScheduleTitle: 'Calendario anual de pagos', yearLabel: 'Año', paymentLabel: 'Total pagado', interestLabel: 'Intereses', principalPaidLabel: 'Capital programado', extraPaidLabel: 'Capital extra', endingBalanceLabel: 'Saldo final', formulaTitle: 'Modelo y límites', formulaText: 'La calculadora usa un modelo de amortización a tipo fijo. En cada periodo calcula los intereses sobre el saldo inicial, aplica la cuota normal a intereses y capital, y después aplica los pagos extra periódicos y puntuales. El interés anual se divide entre el número de periodos de pago. La última cuota se reduce si el saldo restante es menor que la cuota prevista. Al cambiar de moneda, convierte internamente los importes con una proporción de planificación y vuelve a calcular el mismo escenario.', riskNote: 'Es una estimación, no un extracto del banco. El selector usa proporciones internas de planificación, no tipos de cambio en tiempo real. No incluye tipos variables, comisiones, seguros, impuestos, carencias, interés diario, penalizaciones ni las reglas contractuales del banco para aplicar una amortización anticipada.', emptyMessage: 'Introduce un capital, tipo, plazo y fecha válidos para ver el plan.', invalidInputMessage: 'Revisa los datos para ver el plan', currencyOptions: { AUD: 'A$ AUD · dólar australiano', BRL: 'R$ BRL · real brasileño', CAD: 'C$ CAD · dólar canadiense', CHF: 'CHF · franco suizo', CNY: '¥ CNY · yuan chino', CZK: 'Kč CZK · corona checa', DKK: 'kr DKK · corona danesa', EUR: '€ EUR · euro', GBP: '£ GBP · libra esterlina', IDR: 'Rp IDR · rupia indonesia', INR: '₹ INR · rupia india', JPY: '¥ JPY · yen japonés', KRW: '₩ KRW · won surcoreano', MXN: 'MX$ MXN · peso mexicano', NOK: 'kr NOK · corona noruega', PLN: 'zł PLN · zloty polaco', RUB: '₽ RUB · rublo ruso', SEK: 'kr SEK · corona sueca', TRY: '₺ TRY · lira turca', USD: '$ USD · dólar estadounidense' }, currencySymbols: { AUD: 'A$', BRL: 'R$', CAD: 'C$', CHF: 'CHF', CNY: '¥', CZK: 'Kč', DKK: 'kr', EUR: '€', GBP: '£', IDR: 'Rp', INR: '₹', JPY: '¥', KRW: '₩', MXN: 'MX$', NOK: 'kr', PLN: 'zł', RUB: '₽', SEK: 'kr', TRY: '₺', USD: '$' }, frequencyOptions: { monthly: 'Mensual', biweekly: 'Cada dos semanas', weekly: 'Semanal' },
|
|
11
|
+
};
|
|
12
|
+
const faq = [
|
|
13
|
+
{ question: '¿Cómo cambian el calendario los pagos extra?', answer: 'La calculadora mantiene la cuota normal y aplica el capital extra después de cada pago previsto. El saldo puede llegar a cero antes y los intereses totales pueden bajar. El banco puede aplicar la amortización de otra forma, así que compara el resultado con tu contrato.' },
|
|
14
|
+
{ question: '¿Qué ocurre al cambiar de moneda?', answer: 'La calculadora convierte internamente los importes a la nueva moneda con una proporción de planificación y recalcula el mismo escenario. No es una cotización en tiempo real: sirve para planificar, no para afirmar un cambio actual.' },
|
|
15
|
+
{ question: '¿Por qué solo hay un selector de moneda?', answer: 'La moneda seleccionada se aplica al capital, pagos extra, cuotas, intereses, saldos y tabla anual. Una unidad compartida mantiene el formulario claro y evita mezclar monedas dentro del cálculo.' },
|
|
16
|
+
{ question: '¿Calcula la cuota real de mi banco?', answer: 'Estima un calendario de amortización a tipo fijo. No conoce las reglas de tu contrato, días de cálculo, comisiones, seguros, impuestos, revisiones, penalizaciones ni el tratamiento exacto de una amortización anticipada. Para el importe contractual usa el extracto y el contrato.' },
|
|
17
|
+
];
|
|
18
|
+
const howTo = [
|
|
19
|
+
{ name: 'Elige la moneda', text: 'Selecciona la única moneda que quieres utilizar. Se aplicará a cada importe y resultado.' },
|
|
20
|
+
{ name: 'Describe la hipoteca', text: 'Introduce capital, tipo nominal anual, plazo restante, fecha del primer pago y frecuencia.' },
|
|
21
|
+
{ name: 'Añade pagos extra', text: 'Indica un importe extra por periodo y, si quieres, un pago puntual y el periodo en que sucede.' },
|
|
22
|
+
{ name: 'Lee la comparación', text: 'Compara el saldo original con tu plan y revisa intereses, periodos, fecha estimada y calendario anual.' },
|
|
23
|
+
];
|
|
24
|
+
const faqSchema: WithContext<FAQPage> = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
|
|
25
|
+
const howToSchema: WithContext<HowTo> = { '@context': 'https://schema.org', '@type': 'HowTo', name: title, description, step: howTo.map((step, index) => ({ '@type': 'HowToStep', position: index + 1, name: step.name, text: step.text })) };
|
|
26
|
+
const appSchema: WithContext<SoftwareApplication> = { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: title, description, applicationCategory: 'FinanceApplication', operatingSystem: 'All', offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' }, inLanguage: 'es' };
|
|
27
|
+
const seo: ToolLocaleContent['seo'] = [
|
|
28
|
+
{ type: 'title', text: 'Planifica qué pueden cambiar tus pagos extra', level: 2 },
|
|
29
|
+
{ type: 'paragraph', html: '<p>Un calendario de amortización separa cada cuota entre intereses y capital. Si pagas capital adicional y mantienes la cuota normal, el saldo puede llegar a cero antes. Esta calculadora compara el recorrido original con el que crean tus pagos extra periódicos y puntuales.</p>' },
|
|
30
|
+
{ type: 'paragraph', html: '<p>El resultado es una estimación para un préstamo a tipo fijo. Usa capital, tipo nominal anual, número de periodos y un saldo que cambia tras cada pago. Comisiones, redondeos, días de cálculo y reglas de amortización pueden ser distintos en tu contrato.</p>' },
|
|
31
|
+
{ type: 'title', text: 'Cómo funciona el cálculo', level: 3 },
|
|
32
|
+
{ type: 'paragraph', html: '<p>En cada periodo se calculan intereses sobre el saldo inicial. El tipo anual se divide entre los periodos del año. La cuota normal se reparte entre intereses y capital; después los pagos extra reducen más el saldo.</p>' },
|
|
33
|
+
{ type: 'table', headers: ['Dato', 'Cálculo', 'Interpretación'], rows: [['Tipo periódico', 'Tipo anual / periodos al año', 'Tipo aplicado en cada pago'], ['Cuota normal', 'Fórmula de cuota fija', 'Pago antes del capital extra'], ['Interés del periodo', 'Saldo inicial x tipo periódico', 'Interés que supone el modelo'], ['Saldo posterior', 'Saldo inicial - capital - extras', 'Importe que aún queda por pagar']] },
|
|
34
|
+
{ type: 'title', text: 'Qué cambian realmente los pagos extra', level: 3 },
|
|
35
|
+
{ type: 'paragraph', html: '<p>En este modelo, un pago extra se aplica al capital, por lo que los intereses futuros se calculan sobre un saldo menor. Mira tanto los intereses ahorrados como los periodos ahorrados: uno muestra el coste financiero evitado y el otro cuánto se adelanta la liquidación.</p>' },
|
|
36
|
+
{ type: 'paragraph', html: '<p>El banco puede reducir la cuota, mantener el plazo o pedir una solicitud formal. Algunos contratos fijan límites o compensaciones. Usa la salida para preparar preguntas, no para sustituir el documento bancario.</p>' },
|
|
37
|
+
{ type: 'title', text: 'Usa monedas sin mezclar el cálculo', level: 3 },
|
|
38
|
+
{ type: 'paragraph', html: '<p>Elige una moneda antes de introducir importes. El selector se aplica al capital, extras, cuotas, intereses y saldos. Al cambiarla, los importes se convierten internamente y la estructura del escenario permanece.</p>' },
|
|
39
|
+
{ type: 'list', items: ['Elige la moneda de tu presupuesto o extracto.', 'Mantén capital y pagos extra en la moneda seleccionada.', 'Interpreta el cambio como una unidad de planificación, no como un cambio de contrato.', 'Comprueba la frecuencia admitida y las reglas de amortización anticipada.', 'Revisa la tabla anual para localizar el efecto del pago puntual.'] },
|
|
40
|
+
{ type: 'title', text: 'Ejemplo sencillo para interpretar la salida', level: 3 },
|
|
41
|
+
{ type: 'paragraph', html: '<p>Con 250.000 EUR, un tipo fijo del 3,5% y 25 años, añadir 150 EUR por periodo y 5.000 EUR en el periodo 12 no modifica la cuota normal original de este modelo. Sí reduce el saldo posterior, los intereses futuros y la fecha estimada de liquidación.</p>' },
|
|
42
|
+
{ type: 'paragraph', html: '<p>Si cambias a USD, la herramienta convierte los importes con su proporción interna y recalcula el mismo escenario. Es útil para presupuestos internacionales, pero no es una valoración de mercado ni una cotización actual.</p>' },
|
|
43
|
+
{ type: 'title', text: 'Qué comprobar antes de actuar', level: 3 },
|
|
44
|
+
{ type: 'list', items: ['Pregunta si el pago extra reduce plazo o cuota.', 'Comprueba límites anuales, mínimos y posibles compensaciones.', 'Confirma si el tipo es nominal, efectivo, fijo o variable.', 'Compara el saldo calculado con un extracto reciente.', 'Anota el tipo de cambio y la fecha si forma parte de tu presupuesto internacional.'] },
|
|
45
|
+
{ type: 'tip', title: 'El gráfico compara; no promete', html: '<p>La línea discontinua representa el calendario fijo original sin extras. La línea cobre sigue tus datos. Ninguna incluye comisiones, seguros, impuestos, interés diario, movimientos del mercado de divisas o la garantía de que el banco aplique el pago de la misma manera.</p>' },
|
|
46
|
+
{ type: 'title', text: 'Límites de esta calculadora hipotecaria', level: 3 },
|
|
47
|
+
{ type: 'paragraph', html: '<p>La herramienta modela un préstamo totalmente amortizable a tipo fijo con pagos regulares y capital extra opcional. Sirve para explorar escenarios y preparar preguntas. No determina solvencia, no da asesoramiento fiscal o legal, no predice divisas y no sustituye al banco.</p>' },
|
|
48
|
+
];
|
|
49
|
+
export const content: ToolLocaleContent<MortgageExtraPaymentPlannerUI> = { slug, title, description, ui, faq, bibliography, howTo, schemas: [appSchema, faqSchema, howToSchema], seo };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { bibliography } from "../bibliography";
|
|
2
|
+
import type { FAQPage, HowTo, SoftwareApplication, WithContext } from "schema-dts";
|
|
3
|
+
import type { ToolLocaleContent } from "../../../types";
|
|
4
|
+
import type { MortgageExtraPaymentPlannerUI } from "../ui";
|
|
5
|
+
|
|
6
|
+
const slug = "calculateur-amortissement-hypotheque-remboursements-anticipes";
|
|
7
|
+
const title = "Calculateur d'amortissement hypothécaire avec remboursements anticipés";
|
|
8
|
+
const description = "Planifiez un prêt immobilier à taux fixe avec des remboursements anticipés réguliers ou ponctuels, comparez les intérêts économisés et affichez tous les montants dans une seule devise.";
|
|
9
|
+
const ui: MortgageExtraPaymentPlannerUI = {
|
|
10
|
+
currencyLabel: "Devise", currencyHelp: "Choisissez une fois. Tous les montants du plan utiliseront cette devise.", principalLabel: "Capital initial restant", principalHelp: "Montant encore dû au début de ce plan", annualRateLabel: "Taux d'intérêt annuel", annualRateHelp: "Taux nominal fixe appliqué à chaque période", termLabel: "Durée restante en années", termHelp: "Durée prévue avant les remboursements anticipés", frequencyLabel: "Fréquence des paiements", recurringExtraLabel: "Remboursement anticipé régulier", recurringExtraHelp: "Capital supplémentaire payé à chaque période", oneOffExtraLabel: "Remboursement anticipé ponctuel", oneOffExtraHelp: "Un paiement unique de capital pendant la période indiquée", oneOffPeriodLabel: "Période du paiement ponctuel", oneOffPeriodHelp: "1 correspond à la première période", startDateLabel: "Date du premier paiement", startDateHelp: "Sert à estimer la date de remboursement", extraSectionTitle: "Plan de remboursements anticipés", outputTitle: "Évolution du solde", regularPaymentLabel: "Paiement normal avant les extras", interestSavedLabel: "Intérêts économisés", periodsSavedLabel: "périodes gagnées", payoffDateLabel: "Remboursement estimé", totalInterestLabel: "Intérêts payés avec ce plan", totalExtraLabel: "Capital supplémentaire payé", baselineLabel: "Échéancier initial", planLabel: "Avec vos remboursements anticipés", balanceSceneLabel: "Solde initial comparé au solde après les remboursements anticipés", balanceSceneHelp: "La ligne en pointillés montre l'échéancier initial. La ligne cuivrée montre votre plan. Les repères verts indiquent du capital supplémentaire.", annualScheduleTitle: "Échéancier annuel", yearLabel: "Année", paymentLabel: "Total payé", interestLabel: "Intérêts", principalPaidLabel: "Capital prévu", extraPaidLabel: "Capital supplémentaire", endingBalanceLabel: "Solde final", formulaTitle: "Modèle et limites", formulaText: "Le calculateur utilise un modèle d'amortissement à taux fixe. Chaque période calcule les intérêts sur le solde d'ouverture, applique le paiement normal aux intérêts et au capital, puis applique les remboursements anticipés réguliers et ponctuels. Le taux annuel est divisé par le nombre de périodes. Le dernier paiement est réduit si le solde est inférieur au paiement prévu. Un changement de devise convertit les montants avec un ratio interne de planification avant de recalculer le même scénario.", riskNote: "Ceci est une estimation, pas un relevé du prêteur. Le sélecteur utilise des ratios internes de planification, pas des cours de marché en direct. Les taux variables, frais, assurances, impôts, intérêts journaliers, pénalités et règles contractuelles ne sont pas inclus.", emptyMessage: "Saisissez un capital, un taux, une durée et une date valides pour voir le plan.", invalidInputMessage: "Vérifiez les données pour voir le plan", currencyOptions: { AUD: "A$ AUD · dollar australien", BRL: "R$ BRL · réal brésilien", CAD: "C$ CAD · dollar canadien", CHF: "CHF · franc suisse", CNY: "¥ CNY · yuan chinois", CZK: "Kč CZK · couronne tchèque", DKK: "kr DKK · couronne danoise", EUR: "€ EUR · euro", GBP: "£ GBP · livre sterling", IDR: "Rp IDR · roupie indonésienne", INR: "₹ INR · roupie indienne", JPY: "¥ JPY · yen japonais", KRW: "₩ KRW · won sud-coréen", MXN: "MX$ MXN · peso mexicain", NOK: "kr NOK · couronne norvégienne", PLN: "zł PLN · zloty polonais", RUB: "₽ RUB · rouble russe", SEK: "kr SEK · couronne suédoise", TRY: "₺ TRY · livre turque", USD: "$ USD · dollar américain" }, currencySymbols: { AUD: "A$", BRL: "R$", CAD: "C$", CHF: "CHF", CNY: "¥", CZK: "Kč", DKK: "kr", EUR: "€", GBP: "£", IDR: "Rp", INR: "₹", JPY: "¥", KRW: "₩", MXN: "MX$", NOK: "kr", PLN: "zł", RUB: "₽", SEK: "kr", TRY: "₺", USD: "$" }, frequencyOptions: { monthly: "Mensuelle", biweekly: "Toutes les deux semaines", weekly: "Hebdomadaire" },
|
|
11
|
+
};
|
|
12
|
+
const faq = [
|
|
13
|
+
{ question: "Comment les paiements supplémentaires changent-ils l'échéancier ?", answer: "Le calculateur garde le paiement normal et applique le capital supplémentaire après chaque paiement prévu. Le solde peut atteindre zéro plus tôt et les intérêts totaux peuvent diminuer. Le prêteur peut traiter un remboursement anticipé autrement: comparez le résultat au contrat." },
|
|
14
|
+
{ question: "Que se passe-t-il si je change de devise ?", answer: "Les montants sont convertis dans la nouvelle devise avec un ratio interne de planification, puis le même scénario est recalculé. Ce ratio n'est pas un cours en direct: utilisez le résultat pour planifier, pas comme cotation actuelle." },
|
|
15
|
+
{ question: "Pourquoi n'y a-t-il qu'un seul sélecteur de devise ?", answer: "La devise choisie s'applique au capital, aux remboursements anticipés, aux paiements, aux intérêts, aux soldes et à l'échéancier annuel. Une unité commune évite de mélanger les devises." },
|
|
16
|
+
{ question: "Le calculateur donne-t-il mon paiement réel ?", answer: "Il estime un échéancier à taux fixe. Il ne connaît pas les jours de calcul, frais, assurances, impôts, révisions, pénalités ou règles contractuelles de votre prêteur. Utilisez votre relevé et votre contrat pour le montant contractuel." },
|
|
17
|
+
];
|
|
18
|
+
const howTo = [{ name: "Choisir la devise", text: "Sélectionnez la devise unique à appliquer à tous les montants et résultats." }, { name: "Décrire le prêt", text: "Saisissez le capital, le taux nominal annuel, la durée restante, la date du premier paiement et la fréquence." }, { name: "Ajouter les remboursements", text: "Saisissez un montant régulier, puis ajoutez si besoin un paiement ponctuel et sa période." }, { name: "Lire la comparaison", text: "Comparez le solde initial et votre plan, puis consultez les intérêts, périodes, date estimée et échéancier annuel." }];
|
|
19
|
+
const faqSchema: WithContext<FAQPage> = { "@context": "https://schema.org", "@type": "FAQPage", mainEntity: faq.map((item) => ({ "@type": "Question", name: item.question, acceptedAnswer: { "@type": "Answer", text: item.answer } })) };
|
|
20
|
+
const howToSchema: WithContext<HowTo> = { "@context": "https://schema.org", "@type": "HowTo", name: title, description, step: howTo.map((step, index) => ({ "@type": "HowToStep", position: index + 1, name: step.name, text: step.text })) };
|
|
21
|
+
const appSchema: WithContext<SoftwareApplication> = { "@context": "https://schema.org", "@type": "SoftwareApplication", name: title, description, applicationCategory: "FinanceApplication", operatingSystem: "All", offers: { "@type": "Offer", price: "0", priceCurrency: "EUR" }, inLanguage: "fr" };
|
|
22
|
+
const seo: ToolLocaleContent["seo"] = [
|
|
23
|
+
{ type: "title", text: "Planifier l'effet des remboursements anticipés", level: 2 }, { type: "paragraph", html: "<p>Un échéancier d'amortissement sépare chaque paiement entre intérêts et capital. En payant du capital supplémentaire tout en conservant le paiement normal, vous pouvez atteindre zéro plus tôt. Cet outil compare le solde initial au parcours créé par vos remboursements réguliers et ponctuels.</p>" }, { type: "paragraph", html: "<p>Le résultat est une estimation pour un prêt à taux fixe. Il utilise le capital, le taux nominal annuel, le nombre de périodes et un solde qui évolue après chaque paiement. Les contrats peuvent appliquer d'autres conventions de jours, arrondis, frais ou règles d'anticipation.</p>" }, { type: "title", text: "Comment fonctionne le calcul d'amortissement", level: 3 }, { type: "paragraph", html: "<p>À chaque période, les intérêts sont calculés sur le solde d'ouverture. Le taux annuel est divisé par le nombre de périodes de paiement. Le paiement normal est ensuite réparti entre intérêts et capital, puis les remboursements supplémentaires réduisent encore le solde.</p>" }, { type: "table", headers: ["Élément", "Calcul", "Interprétation"], rows: [["Taux périodique", "Taux annuel / périodes par an", "Taux appliqué à chaque période"], ["Paiement normal", "Formule de paiement fixe", "Paiement avant le capital supplémentaire"], ["Intérêts", "Solde d'ouverture x taux périodique", "Intérêts supposés par le modèle"], ["Solde après paiement", "Solde - capital - extras", "Montant restant dû"]] }, { type: "title", text: "Ce que changent les paiements supplémentaires", level: 3 }, { type: "paragraph", html: "<p>Dans ce modèle, un remboursement supplémentaire réduit directement le capital. Les intérêts futurs portent donc sur un solde plus faible. Consultez à la fois les intérêts économisés et les périodes gagnées: l'un mesure le coût financier évité, l'autre l'avance de la date de remboursement.</p>" }, { type: "paragraph", html: "<p>Le prêteur peut réduire le paiement, conserver la durée ou demander une démarche formelle. Vérifiez les plafonds annuels, les montants minimums et les indemnités éventuelles.</p>" }, { type: "title", text: "Utiliser les devises sans mélanger les montants", level: 3 }, { type: "paragraph", html: "<p>Choisissez une devise avant de saisir les montants. Elle s'applique au capital, aux extras, aux paiements, aux intérêts et aux soldes. Lors d'un changement, les montants sont convertis en interne et la structure du scénario reste identique.</p>" }, { type: "list", items: ["Choisissez la devise de votre budget ou relevé.", "Saisissez le capital et les extras dans cette unité.", "Considérez le changement comme une unité de planification, pas comme une modification du contrat.", "Vérifiez la fréquence autorisée et les règles de remboursement anticipé.", "Consultez l'échéancier annuel pour voir l'effet du paiement ponctuel."] }, { type: "title", text: "Un exemple simple pour lire le résultat", level: 3 }, { type: "paragraph", html: "<p>Avec 250 000 EUR, un taux fixe de 3,5 % et 25 ans, un extra de 150 EUR par période et 5 000 EUR à la période 12 ne changent pas le paiement normal de départ dans ce modèle. Ils réduisent le solde et les intérêts futurs.</p>" }, { type: "paragraph", html: "<p>En passant en USD, l'outil convertit les montants avec son ratio interne et recalcule le même scénario. C'est une aide de budget international, pas une valeur de marché ni un cours actuel.</p>" }, { type: "title", text: "Vérifications avant d'agir", level: 3 }, { type: "list", items: ["Demandez si l'extra réduit la durée ou le paiement.", "Vérifiez plafonds, minimums et indemnités.", "Confirmez si le taux est nominal, effectif, fixe ou variable.", "Comparez le solde calculé à un relevé récent.", "Notez le cours et la date pour un budget international."] }, { type: "tip", title: "Le graphique compare, il ne garantit rien", html: "<p>La ligne en pointillés représente le plan fixe sans extras et la ligne cuivrée suit vos données. Ni l'une ni l'autre n'inclut frais, assurance, impôts, intérêts journaliers, mouvements de change ou règles particulières du prêteur.</p>" }, { type: "title", text: "Limites de ce calculateur hypothécaire", level: 3 }, { type: "paragraph", html: "<p>L'outil modélise un prêt amortissable à taux fixe avec paiements réguliers et capital supplémentaire facultatif. Il aide à explorer des scénarios et préparer des questions, mais ne mesure pas la capacité d'emprunt, ne donne pas de conseil fiscal ou juridique et ne remplace pas le relevé du prêteur.</p>" },
|
|
24
|
+
];
|
|
25
|
+
export const content: ToolLocaleContent<MortgageExtraPaymentPlannerUI> = { slug, title, description, ui, faq, bibliography, howTo, schemas: [appSchema, faqSchema, howToSchema], seo };
|