diff --git a/src/components/AdminRoute.jsx b/src/components/AdminRoute.jsx
index 8015120..5ea4444 100644
--- a/src/components/AdminRoute.jsx
+++ b/src/components/AdminRoute.jsx
@@ -9,7 +9,7 @@ export default function AdminRoute({ children }) {
return (
-
Loading...
+
Wird geladen …
)
}
diff --git a/src/components/finance/TaxCard.jsx b/src/components/finance/TaxCard.jsx
index d997767..debd7e8 100644
--- a/src/components/finance/TaxCard.jsx
+++ b/src/components/finance/TaxCard.jsx
@@ -5,6 +5,7 @@ import { taxView } from '../../lib/financeView'
* Block 4: „Steuer“. Rücklage (Betrag und woraus sie sich ergibt), Kleinunternehmer-Zähler gegen die Grenzen,
* Vorjahr (nur wenn eingetragen), Gewerbesteuer-Hinweis (nur wenn nötig) und die nächste ESt-Vorauszahlung
* (nur wenn eingestellt). Ist der Zähler unbekannt (Stripe nicht erreichbar), steht das als Text da, nie eine 0.
+ * Am Ende steht immer der Hinweis „Orientierungswert, ersetzt keine Steuerberatung.“
*/
export default function TaxCard({ steuer }) {
const v = taxView(steuer)
@@ -44,6 +45,8 @@ export default function TaxCard({ steuer }) {
am {v.prepayment.dateText}
)}
+
+ {v.noteText}
)
diff --git a/src/lib/financeView.js b/src/lib/financeView.js
index 4775d23..f1f08f3 100644
--- a/src/lib/financeView.js
+++ b/src/lib/financeView.js
@@ -292,10 +292,13 @@ const KLEIN_LIMIT_CENTS = 2_500_000
const KLEIN_HARD_LIMIT_CENTS = 10_000_000
const GEWERBE_ALLOWANCE_CENTS = 2_450_000
+/** Dauerhafter Hinweis unter den Steuerwerten: die Zahlen sind Näherungen. */
+export const TAX_NOTE = 'Orientierungswert, ersetzt keine Steuerberatung.'
+
/**
* Texte der Steuerkarte aus `steuer`:
* { reserve: { amountText, basisText }, small: { known, counterText, shareText, limitText, hardText, previousText },
- * gewerbeText, prepayment: { dateText, amountText } | null }.
+ * gewerbeText, prepayment: { dateText, amountText } | null, noteText }.
* Ist der Kleinunternehmer-Zähler null (Stripe nicht erreichbar), steht „unbekannt“ statt einer Zahl.
*/
export function taxView(steuer) {
@@ -331,7 +334,7 @@ export function taxView(steuer) {
counterText: known ? `${euro(k.jahrCents)} von ${euroWhole(limit)}${year !== null ? ` (${year})` : ''}` : 'unbekannt (Stripe nicht erreichbar)',
shareText:
known && isNum(k.anteilFolgejahr)
- ? `${percentDe(k.anteilFolgejahr * 100, 1)} % der ${euroWhole(limit).replace(' €', '-€')}-Grenze`
+ ? `${percentDe(k.anteilFolgejahr * 100, 1)} % der Grenze von ${euroWhole(limit)}`
: null,
limitText: `Über ${euroWhole(limit)} im Jahr${year !== null ? ` ${year}` : ''}: ab ${
year !== null ? year + 1 : 'dem Folgejahr'
@@ -344,6 +347,7 @@ export function taxView(steuer) {
? `Der Gewinn${year !== null ? ` ${year}` : ''} liegt über dem Gewerbesteuer-Freibetrag von ${euroWhole(GEWERBE_ALLOWANCE_CENTS)} (natürliche Personen und Personengesellschaften, § 11 GewStG). Auf den übersteigenden Gewerbeertrag kann Gewerbesteuer anfallen.`
: null,
prepayment,
+ noteText: TAX_NOTE,
}
}
diff --git a/tests/unit/adminRoute.test.mjs b/tests/unit/adminRoute.test.mjs
new file mode 100644
index 0000000..b2f1be8
--- /dev/null
+++ b/tests/unit/adminRoute.test.mjs
@@ -0,0 +1,14 @@
+import test from 'node:test'
+import assert from 'node:assert/strict'
+import { readFileSync } from 'node:fs'
+import path from 'node:path'
+import { fileURLToPath } from 'node:url'
+
+const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..')
+const source = readFileSync(path.join(root, 'src/components/AdminRoute.jsx'), 'utf8')
+
+// AdminRoute braucht React und den Auth-Kontext (nicht unter Node ladbar): der Ladetext wird am Quelltext geprüft
+test('AdminRoute: Ladetext auf Deutsch, kein englisches „Loading...“', () => {
+ assert.match(source, /Wird geladen …<\/p>/)
+ assert.doesNotMatch(source, /Loading/)
+})
diff --git a/tests/unit/financeView.test.mjs b/tests/unit/financeView.test.mjs
index 6d03fa2..2b2ef61 100644
--- a/tests/unit/financeView.test.mjs
+++ b/tests/unit/financeView.test.mjs
@@ -20,6 +20,7 @@ const {
forecastRows,
forecastNotes,
taxView,
+ TAX_NOTE,
aboView,
productLabel,
aboStatus,
@@ -453,17 +454,25 @@ test('taxView: Kleinunternehmer-Zähler „ von 25.000 € (2026)“ und
const v = taxView(steuer())
assert.equal(v.small.known, true)
assert.equal(v.small.counterText, '80,00 € von 25.000 € (2026)')
- assert.equal(v.small.shareText, '0,3 % der 25.000-€-Grenze')
+ assert.equal(v.small.shareText, '0,3 % der Grenze von 25.000 €')
assert.equal(v.small.limitText, 'Über 25.000 € im Jahr 2026: ab 2027 keine Kleinunternehmerregelung.')
assert.equal(
v.small.hardText,
'Grenze 100.000 €: Ab dem Umsatz, der diese Grenze übersteigt, gilt schon im laufenden Jahr die Regelbesteuerung (Umsatzsteuer).'
)
assert.equal(v.small.previousText, null)
- assert.equal(taxView(steuer({}, { anteilFolgejahr: 0.704 })).small.shareText, '70,4 % der 25.000-€-Grenze')
+ assert.equal(taxView(steuer({}, { anteilFolgejahr: 0.704 })).small.shareText, '70,4 % der Grenze von 25.000 €')
assert.equal(taxView(steuer({}, { jahrCents: 0, anteilFolgejahr: 0 })).small.counterText, '0,00 € von 25.000 € (2026)')
})
+test('taxView: Orientierungshinweis steht immer dabei, Anteil ohne „-€-Grenze“', () => {
+ assert.equal(TAX_NOTE, 'Orientierungswert, ersetzt keine Steuerberatung.')
+ assert.equal(taxView(steuer()).noteText, TAX_NOTE)
+ assert.equal(taxView(null).noteText, TAX_NOTE)
+ assert.equal(taxView(steuer({}, { jahrCents: null, anteilFolgejahr: null })).noteText, TAX_NOTE)
+ for (const t of [taxView(steuer()), taxView(steuer({}, { anteilFolgejahr: 1.2 }))]) assert.doesNotMatch(t.small.shareText, /-€-Grenze/)
+})
+
test('taxView: Stripe nicht erreichbar -> unbekannt statt 0', () => {
const v = taxView(steuer({}, { jahrCents: null, anteilFolgejahr: null }))
assert.equal(v.small.known, false)
@@ -492,7 +501,7 @@ test('taxView: Vorjahr nur wenn gesetzt, über der Grenze mit Hinweis', () => {
test('taxView: Grenzen kommen aus dem Server (Rückfall nur ohne Wert), Jahr fehlt -> Folgejahr', () => {
const custom = taxView(steuer({ jahr: 2030 }, { grenzeFolgejahrCents: 3000000, grenzeHartCents: 12000000, anteilFolgejahr: 0.5, vorjahrCents: 3000001 }))
assert.equal(custom.small.counterText, '80,00 € von 30.000 € (2030)')
- assert.equal(custom.small.shareText, '50 % der 30.000-€-Grenze')
+ assert.equal(custom.small.shareText, '50 % der Grenze von 30.000 €')
assert.equal(custom.small.limitText, 'Über 30.000 € im Jahr 2030: ab 2031 keine Kleinunternehmerregelung.')
assert.match(custom.small.hardText, /^Grenze 120\.000 €: Ab dem Umsatz, der diese Grenze übersteigt, gilt schon im laufenden Jahr die Regelbesteuerung \(Umsatzsteuer\)\.$/)
assert.equal(custom.small.previousText, 'Vorjahr: 30.000,01 € (über 30.000 €: im laufenden Jahr keine Kleinunternehmerregelung)')