-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrechner.py
More file actions
116 lines (89 loc) · 3.55 KB
/
rechner.py
File metadata and controls
116 lines (89 loc) · 3.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env python3
"""
Forschungszulage-Rechner (FZulG) - Kommandozeilen-Version
Berechnet die steuerliche Forschungszulage fuer Solo-Selbststaendige.
Beruecksichtigt die gestaffelten Saetze (Stichtage 28.03.2024 und 01.01.2026).
Interaktiver Rechner: https://martinmeng.de/rechner
"""
import sys
from datetime import date
STUFEN = [
{"von": date(2020, 1, 1), "bis": date(2024, 3, 27), "satz_h": 40, "foerder": 0.25, "label": "Bis 27.03.2024"},
{"von": date(2024, 3, 28), "bis": date(2025, 12, 31), "satz_h": 70, "foerder": 0.35, "label": "28.03.2024 - 31.12.2025 (KMU)"},
{"von": date(2026, 1, 1), "bis": date(2030, 12, 31), "satz_h": 100, "foerder": 0.35, "label": "Ab 01.01.2026 (KMU)"},
]
MAX_STUNDEN_WOCHE = 40
MAX_STUNDEN_JAHR = 2080 # 52 Wochen x 40h
def get_stufe(jahr: int) -> dict:
"""Ermittelt die gueltige Foerderstufe fuer ein Jahr."""
stichtag = date(jahr, 7, 1) # Mitte des Jahres als Referenz
for s in STUFEN:
if s["von"] <= stichtag <= s["bis"]:
return s
return STUFEN[-1]
def berechne(stunden_pro_jahr: dict[int, float]) -> dict:
"""
Berechnet die Forschungszulage fuer mehrere Jahre.
Args:
stunden_pro_jahr: {2022: 1200, 2023: 1500, ...}
Returns:
Dict mit Ergebnissen pro Jahr und Gesamtsumme.
"""
ergebnisse = {}
gesamt = 0.0
for jahr, stunden in sorted(stunden_pro_jahr.items()):
if stunden <= 0:
continue
if stunden > MAX_STUNDEN_JAHR:
print(f" Warnung: {stunden}h in {jahr} ueberschreitet {MAX_STUNDEN_JAHR}h/Jahr (40h/Woche)")
stunden = MAX_STUNDEN_JAHR
stufe = get_stufe(jahr)
bemessungsgrundlage = stunden * stufe["satz_h"]
zulage = bemessungsgrundlage * stufe["foerder"]
ergebnisse[jahr] = {
"stunden": stunden,
"satz_h": stufe["satz_h"],
"foerdersatz": stufe["foerder"],
"bemessungsgrundlage": bemessungsgrundlage,
"zulage": zulage,
"stufe": stufe["label"],
}
gesamt += zulage
return {"jahre": ergebnisse, "gesamt": gesamt}
def main():
print("=" * 50)
print("Forschungszulage-Rechner (FZulG)")
print("Fuer Solo-Selbststaendige und Freelancer")
print("https://martinmeng.de/rechner")
print("=" * 50)
print()
stunden = {}
if len(sys.argv) > 1:
# CLI-Modus: rechner.py 2022=1200 2023=1500 2024=1800
for arg in sys.argv[1:]:
if "=" in arg:
jahr, h = arg.split("=")
stunden[int(jahr)] = float(h)
else:
# Interaktiver Modus
print("Gib deine FuE-Stunden pro Jahr ein (leer = ueberspringen):\n")
for jahr in range(2022, 2027):
stufe = get_stufe(jahr)
inp = input(f" {jahr} ({stufe['satz_h']} EUR/h, {int(stufe['foerder']*100)}%): ")
if inp.strip():
stunden[int(jahr)] = float(inp.strip())
if not stunden:
print("\nKeine Stunden eingegeben.")
sys.exit(0)
ergebnis = berechne(stunden)
print(f"\n{'─' * 50}")
print(f"{'Jahr':<6} {'Stunden':>8} {'Satz':>8} {'Basis':>12} {'Zulage':>12}")
print(f"{'─' * 50}")
for jahr, e in ergebnis["jahre"].items():
print(f"{jahr:<6} {e['stunden']:>7.0f}h {e['satz_h']:>6} EUR {e['bemessungsgrundlage']:>10,.0f} EUR {e['zulage']:>10,.0f} EUR")
print(f"{'─' * 50}")
print(f"{'GESAMT':<6} {'':>8} {'':>8} {'':>12} {ergebnis['gesamt']:>10,.0f} EUR")
print()
print("Beratung: https://martinmeng.de")
if __name__ == "__main__":
main()