/[lohnrechner]/trunk/lohnrechner.py
ViewVC logotype

Contents of /trunk/lohnrechner.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 81 - (show annotations)
Wed Feb 11 11:04:42 2009 UTC (16 years, 2 months ago) by frank
File MIME type: text/x-python
File size: 14387 byte(s)
Sonstige Bezuege grundsaetzlich eingebunden, aber in der Eingabe deaktiviert.

1 #! /usr/bin/python
2 # -*- coding: iso-8859-1 -*-
3 # --------------------------------------------------------------------
4 # Lohnsteuer und Sozialabgaben Rechner
5 # $Id$
6 # --------------------------------------------------------------------
7 #
8 # Copyright (c) 2005,2006,2007,2008 by Intevation GmbH
9 # Authors:
10 # Sascha Wilde <[email protected]>
11 #
12 # This program is free software under the GPL (>=v2)
13 # Read the file COPYING coming with this package for details.
14
15 """Lohn/Gehaltsrechner für das Jahr 2008"""
16
17 __version__ = "$Revision$"
18 # $Source$
19
20 _release_version = "0.%s" % __version__[11:-2]
21
22 import LST2008
23 from Tkinter import *
24
25 class Lohnrechner(LST2008.LStRechner2008):
26
27 def __init__(self, root):
28 LST2008.LStRechner2008.__init__(self)
29
30 # Land, Kirchensteuersatz, Pflegeversicherung AG-Anteil
31 self.laender = [("Baden-Württemberg", 8, 0.0085, 5300),
32 ("Bayern", 8, 0.0085, 5300),
33 ("Berlin (ost)", 9, 0.0085, 4500),
34 ("Berlin (west)", 9, 0.0085, 5300),
35 ("Brandenburg", 9, 0.0085, 4500),
36 ("Bremen", 9, 0.0085, 5300),
37 ("Bremerhaven", 9, 0.0085, 5300),
38 ("Hamburg", 9, 0.0085, 5300),
39 ("Hessen", 9, 0.0085, 5300),
40 ("Mecklenburg-Vorpommern", 9, 0.0085, 4500),
41 ("Niedersachsen" ,9, 0.0085, 5300),
42 ("Nordrhein-Westfalen", 9, 0.0085, 5300),
43 ("Rheinland-Pfalz", 9, 0.0085, 5300),
44 ("Saarland", 9, 0.0085, 5300),
45 ("Sachsen", 9, 0.0135, 4500),
46 ("Sachsen-Anhalt", 9, 0.0085, 4500),
47 ("Schleswig-Holstein", 9, 0.0085, 5300),
48 ("Thüringen", 9, 0.0085, 4500)]
49
50 self.root = root
51
52 self.root.title("Lohnrechner 2008 - v%s" % _release_version)
53
54 self.SetupUI()
55 self.UpdateLand()
56 self.InitSozv()
57 self.ResetInput()
58
59 def SetupUI(self):
60 self.root.resizable(NO, NO)
61
62 frame = Frame(self.root)
63 frame.grid(padx=10, pady=10)
64
65 # Steuern Ein/Ausgabe
66 Label(frame, text="Geburtsjahr:").grid(row=0, sticky=E)
67 self.geb = Entry(frame)
68 self.geb.bind("<Return>", self.NewInput)
69 self.geb.grid(row=0, column=1, sticky=W)
70
71 Label(frame, text="Lohn (monatlich):").grid(row=1, sticky=E)
72 self.lohn = Entry(frame)
73 self.lohn.bind("<Return>", self.NewInput)
74 self.lohn.grid(row=1, column=1, sticky=W)
75
76 sonstbezlabel = Label(frame, text="Sonstige Bezüge:")
77 self.sonstbez = Entry(frame)
78 self.sonstbez.bind("<Return>", self.NewInput)
79 # Sonstige Bezuege bisher nur unter Randbedingungen:
80 # - Einmalig im Kalenderjahr
81 # - Keine Berücksichtigung bei der Berechnung Sozialbeiträge
82 # Daher per Vorgabe "versteckt", bei Bedarf einfuegen:
83 # sonstbezlabel.grid(row=2, sticky=E)
84 # self.sonstbez.grid(row=2, column=1, sticky=W)
85
86 Label(frame, text="Steuerklasse:").grid(row=3, sticky=E)
87 self.stkl = IntVar()
88 stklframe = Frame(frame)
89 stklframe.grid(row=3, column=1, sticky=W)
90 for text, val in [("I", 1),
91 ("II", 2),
92 ("III", 3),
93 ("IV", 4),
94 ("V", 5),
95 ("VI", 6)]:
96 stklradio = Radiobutton(stklframe, text=text, value=val,
97 indicatoron=0, command=self.NewInput,
98 variable=self.stkl)
99 if text == "I":
100 stklradio.select()
101 stklradio.pack(side=LEFT)
102
103 Label(frame, text="Kirchensteuer:").grid(row=4, sticky=E)
104 self.kirche = IntVar()
105 Checkbutton(frame, onvalue=1, offvalue=0, command=self.NewInput,
106 variable=self.kirche).grid(row=4, column=1,sticky=W)
107
108 Label(frame, text="Kinderfreibetrag:").grid(row=5, sticky=E)
109 self.kfb = Entry(frame)
110 self.kfb.bind("<Return>", self.NewInput)
111 self.kfb.grid(row=5, column=1, sticky=W)
112
113 Label(frame, text="Kinder:").grid(row=6, sticky=E)
114 self.kinder = IntVar()
115 self.kinderradio = Checkbutton(frame, onvalue=1, offvalue=0,
116 command=self.NewInput,
117 variable=self.kinder)
118 self.kinderradio.grid(row=6, column=1, sticky=W)
119
120 Label(frame, text="Bundesland:").grid(row=7, sticky=NE)
121 landframe = Frame(frame)
122 scrollbar = Scrollbar(landframe, orient=VERTICAL)
123 self.landbox = Listbox(landframe, height=4, selectmode=SINGLE,
124 yscrollcommand=scrollbar.set)
125 for land in self.laender:
126 self.landbox.insert(END, land[0])
127 self.landbox.select_set(0)
128 self.landbox.bind("<<ListboxSelect>>", self.NewLandSel)
129 self.landbox.pack(side=RIGHT, fill=Y)
130 scrollbar.config(command=self.landbox.yview)
131 scrollbar.pack(side=LEFT, fill=BOTH, expand=1)
132 landframe.grid(row=7, rowspan=4, column=1, sticky=W)
133
134 Label(frame, text="Lohnsteuer:").grid(row=0, column=2, sticky=E)
135 self.lst = Entry(frame)
136 self.lst.grid(row=0, column=3, sticky=W)
137
138 Label(frame, text="Solidaritätszuschlag:").grid(row=1, column=2, sticky=E)
139 self.soli = Entry(frame)
140 self.soli.grid(row=1, column=3, sticky=W)
141
142 Label(frame, text="Kirchensteuer:").grid(row=2, column=2, sticky=E)
143 self.kist = Entry(frame)
144 self.kist.grid(row=2, column=3, sticky=W)
145
146 Label(frame, text="Lohn nach Steuern:").grid(row=3, column=2, sticky=E)
147 self.netto1 = Entry(frame)
148 self.netto1.grid(row=3, column=3, sticky=W)
149
150 # Sozialversicherung Ein/Ausgabe
151 Label(frame, text="Sozialversicherung:").grid(row=11, sticky=E)
152 self.sozv = IntVar()
153 sozvradio = Checkbutton(frame, onvalue=1, offvalue=0,
154 command=self.NewInput, variable=self.sozv)
155 sozvradio.select()
156 sozvradio.grid(row=11, column=1, sticky=W)
157
158 Label(frame, text="Krankenkassenbeitrag:").grid(row=12, sticky=E)
159 self.kvsatz = Entry(frame)
160 self.kvsatz.bind("<Return>", self.NewInput)
161 self.kvsatz.grid(row=12, column=1, sticky=W)
162
163 Label(frame, text="Krankenkassenzuschlag (0.9%):").grid(row=13, sticky=E)
164 self.kvsoli = IntVar()
165 kvsoliradio = Checkbutton(frame, onvalue=1, offvalue=0,
166 command=self.NewInput, variable=self.kvsoli)
167 kvsoliradio.select()
168 kvsoliradio.grid(row=13, column=1, sticky=W)
169
170
171 Label(frame, text="Rentenversicherung:").grid(row=4, column=2, sticky=E)
172 self.rv = Entry(frame)
173 self.rv.grid(row=4, column=3, sticky=W)
174
175 Label(frame, text="Krankenversicherung:").grid(row=5, column=2, sticky=E)
176 self.kv = Entry(frame)
177 self.kv.grid(row=5, column=3, sticky=W)
178
179 Label(frame, text="Arbeitslosenversicherung:").grid(row=6, column=2,
180 sticky=E)
181 self.av = Entry(frame)
182 self.av.grid(row=6, column=3, sticky=W)
183
184 Label(frame, text="Pflegeversicherung:").grid(row=7, column=2, sticky=E)
185 self.pv = Entry(frame)
186 self.pv.grid(row=7, column=3, sticky=W)
187
188 Label(frame, text="Netto Lohn:").grid(row=8, column=2, sticky=E)
189 self.netto2 = Entry(frame)
190 self.netto2.grid(row=8, column=3, sticky=W)
191
192 # Allgemeine UI Elemente
193 buttons = Frame(frame)
194 buttons.grid(row=10, column=2, rowspan=3, columnspan=2)
195 Button(buttons, text="Quit", command=self.root.quit).pack(side=LEFT)
196 Button(buttons, text="Info", command=self.Info).pack(side=LEFT)
197 Button(buttons, text="Berechnen", command=self.CalcOutput).pack(side=LEFT)
198
199 def NewInput(self, event=0):
200 # Es ist möglich alle Einträge in der Listbox zu deselektieren,
201 # es ist aber immer genau ein Eintrag aktuell, darum wird er ggf.
202 # zwangsselektiert:
203 # FIX ME: eigendlich wäre das ein Fall für ein custom widget!
204 if len(self.landbox.curselection()) == 0:
205 self.landbox.select_set(self.land)
206 if float(self.kfb.get()) > 0.0:
207 self.kinderradio.select()
208 self.CalcOutput()
209
210 def UpdateLand(self):
211 self.land = int(self.landbox.curselection()[0])
212
213 def NewLandSel(self, event=0):
214 self.UpdateLand()
215 self.CalcOutput()
216
217 def ResetInput(self):
218 self.ResetInputGeb()
219 self.ResetInputLohn()
220 self.ResetInputSonstBez()
221 self.ResetInputKfb()
222 self.ResetInputKVsatz()
223 self.NewLandSel()
224
225 def ResetInputGeb(self):
226 self.geb.delete(0, END)
227 self.geb.insert(0, "1964")
228
229 def ResetInputLohn(self):
230 self.lohn.delete(0, END)
231 self.lohn.insert(0, "0")
232
233 def ResetInputSonstBez(self):
234 self.sonstbez.delete(0, END)
235 self.sonstbez.insert(0, "0")
236
237 def ResetInputKfb(self):
238 self.kfb.delete(0, END)
239 self.kfb.insert(0, "0")
240
241 def ResetInputKVsatz(self):
242 self.kvsatz.delete(0, END)
243 self.kvsatz.insert(0, "13.8")
244
245 def InitCalc(self):
246 try:
247 self.SetLohn(float(self.lohn.get()))
248 except:
249 self.ResetInputLohn()
250
251 try:
252 self.SetSonstigeBezuege(float(self.sonstbez.get()))
253 except:
254 self.ResetInputSonstBez()
255
256 # JRE4: Nötig für Sonstige Bezüge.
257 # Voraussichtlicher Jahresarbeitslohn ohne sonstige Bezüge und ohne
258 # Vergütung für mehrjährige Tätigkeit in Cent (ggf. 0)
259 # lohnrechner berechnet diesen aus dem monatlichen Lohn.
260 try:
261 self.Set_JRE4(round(float(self.lohn.get())*100.0,2)*12)
262 except:
263 pass
264
265 # JVBEZ: Nötig für Sonstige Bezüge.
266 # lohnrechner berücksichtigt keine Versorgungsbezüge, daher 0.
267 self.Set_JVBEZ(0)
268
269 try:
270 self.SetGeb(int(self.geb.get()))
271 except:
272 self.ResetInputGeb()
273
274 try:
275 self.SetKinderfreibetrag(float(self.kfb.get()))
276 except:
277 self.ResetInputKfb()
278
279 try:
280 self.SetKV(float(self.kvsatz.get()))
281 except:
282 self.ResetInputKVsatz()
283
284 self.SetSteuerklasse(self.stkl.get())
285 self.SetKirchensteuerProzent(self.kirche.get() *
286 self.laender[self.land][1])
287
288 def CalcOutput(self):
289 self.InitCalc()
290 self.Calc()
291 self.lst.delete(0, END)
292 self.lst.insert(0, "%.2f" % self.GetLohnsteuerGesamt())
293 self.soli.delete(0, END)
294 self.soli.insert(0, "%.2f" % self.GetSoliGesamt())
295 self.kist.delete(0, END)
296 self.kist.insert(0, "%.2f" % self.GetKirchensteuerGesamt())
297 netto1 = self.GetLohn() + self.GetSonstigeBezuege() \
298 - self.GetLohnsteuerGesamt() \
299 - self.GetSoliGesamt() - self.GetKirchensteuerGesamt()
300 self.netto1.delete(0, END)
301 self.netto1.insert(0, "%.2f" % netto1)
302 self.rv.delete(0, END)
303 self.rv.insert(0, "%.2f" % self.GetRV())
304 self.pv.delete(0, END)
305 self.pv.insert(0, "%.2f" % self.GetPV())
306 self.av.delete(0, END)
307 self.av.insert(0, "%.2f" % self.GetAV())
308 self.kv.delete(0, END)
309 self.kv.insert(0, "%.2f" % self.GetKV())
310 netto2 = netto1 - self.GetRV() - self.GetAV() \
311 - self.GetPV() - self.GetKV()
312 self.netto2.delete(0, END)
313 self.netto2.insert(0, "%.2f" % netto2)
314
315 def Info(self):
316 infowin = Toplevel(self.root)
317 infowin.title("Info")
318 Label(infowin, text="Lohnrechner 2008 v%s" % _release_version,
319 font=("Times", 14, "bold italic")).grid(row=0, pady=20)
320 Label(infowin, text=
321 "Copyright (C) 2005,2006,2007,2008 Intevation GmbH \n\n\
322 Lohnrechner 2008 comes with ABSOLUTELY NO WARRANTY.\n\
323 This is free software, and you are welcome to redistribute it\n\
324 under the terms of the GNU General Public License.\n\
325 For more information about these matters, see the file named COPYING.\n\n\
326 Dieses Programm verwendet LST2008 %s" % LST2008._ModulVersion()).grid(row=1, padx=10)
327 Button(infowin, text="Ok", command=infowin.destroy).grid(row=2, pady=10)
328
329 #
330 # Funktionen zur Berechnung der Sozialversicherungsbeiträge.
331 #
332 # FIX ME: Dieser Teil könnte evl. in ein eigenes Modul ausgelagert werden.
333 #
334
335 def InitSozv(self):
336 self.AVsatz = 0.033 / 2
337 self.RVsatz = 0.199 / 2
338 # PVsatz ist in self.laender definiert!
339 self.PVkinderlose = 0.0025
340 self.BMG1 = 3600
341 # BMG2 für RV und ALV ist in self.laender definiert!
342
343 def SetKV(self, value):
344 assert value >= 0.0 and value <= 100.0, \
345 "must be in range 0.0-100.0 (Percent)"
346 self.KVsatz = (value / 100.0)
347
348 def GetAV(self):
349 lohn = self.GetLohnGesamt()
350 BMG2 = self.laender[self.land][3]
351 if lohn > BMG2 : lohn = BMG2
352 return round(self.sozv.get() * self.AVsatz * lohn, 2)
353
354 def GetRV(self):
355 lohn = self.GetLohnGesamt()
356 BMG2 = self.laender[self.land][3]
357 if lohn > BMG2 : lohn = BMG2
358 return round(self.sozv.get() * self.RVsatz * lohn, 2)
359
360 def GetPV(self):
361 self.PVsatz = self.laender[self.land][2]
362 lohn = self.GetLohnGesamt()
363 if lohn > self.BMG1 : lohn = self.BMG1
364 PV = self.PVsatz * lohn
365 if self.kinder.get() == 0 :
366 PV += lohn * self.PVkinderlose
367 return round(self.sozv.get() * PV, 2)
368
369 def GetKV(self):
370 self.KVsoli = self.kvsoli.get()
371 lohn = self.GetLohnGesamt()
372 if lohn > self.BMG1 : lohn = self.BMG1
373 if self.KVsoli :
374 return round(self.sozv.get() * ((self.KVsatz / 2) + 0.009) * lohn, 2)
375 else :
376 return round(self.sozv.get() * self.KVsatz * lohn / 2, 2)
377
378
379 if __name__ == "__main__":
380 root = Tk()
381 lr = Lohnrechner(root)
382 root.mainloop()

Properties

Name Value
svn:eol-style native
svn:executable *
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26