--- trunk/RCS/lohnrechner.py 2005/01/14 13:04:09 22 +++ trunk/lohnrechner.py 2007/01/26 10:38:26 71 @@ -5,63 +5,77 @@ # $Id$ # -------------------------------------------------------------------- # -# Copyright (c) 2005 by Intevation GmbH +# Copyright (c) 2005,2006,2007 by Intevation GmbH # Authors: # Sascha Wilde # # This program is free software under the GPL (>=v2) # Read the file COPYING coming with this package for details. -"""Lohn/Gehaltsrechner für das Jahr 2005""" +"""Lohn/Gehaltsrechner für das Jahr 2007""" __version__ = "$Revision$" # $Source$ -_release_version = "0.%s beta" % __version__[11:-2] +_release_version = "0.%s" % __version__[11:-2] -import LST2005 +import LST2007 from Tkinter import * -class Lohnrechner(LST2005.LStRechner2005): +class Lohnrechner(LST2007.LStRechner2007): def __init__(self, root): - LST2005.LStRechner2005.__init__(self) + LST2007.LStRechner2007.__init__(self) - # Land, Kirchensteuersatz - self.laender = [("Baden-Württemberg", 8), - ("Bayern", 8), - ("Berlin", 9), - ("Brandenburg", 9), - ("Bremen", 9), - ("Bremerhaven", 9), - ("Hamburg", 9), - ("Hessen", 9), - ("Mecklenburg-Vorpommern", 9), - ("Niedersachsen" ,9), - ("Nordrhein-Westfalen", 9), - ("Rheinland-Pfalz", 9), - ("Saarland", 9), - ("Sachsen", 9), - ("Sachsen-Anhalt", 9), - ("Schleswig-Holstein", 9), - ("Thüringen", 9)] - - root.title("Lohnrechner 2005 - v%s" % _release_version) - root.resizable(NO, NO) + # Land, Kirchensteuersatz, Pflegeversicherung AG-Anteil + self.laender = [("Baden-Württemberg", 8, 0.0085), + ("Bayern", 8, 0.0085), + ("Berlin", 9, 0.0085), + ("Brandenburg", 9, 0.0085), + ("Bremen", 9, 0.0085), + ("Bremerhaven", 9, 0.0085), + ("Hamburg", 9, 0.0085), + ("Hessen", 9, 0.0085), + ("Mecklenburg-Vorpommern", 9, 0.0085), + ("Niedersachsen" ,9, 0.0085), + ("Nordrhein-Westfalen", 9, 0.0085), + ("Rheinland-Pfalz", 9, 0.0085), + ("Saarland", 9, 0.0085), + ("Sachsen", 9, 0.0135), + ("Sachsen-Anhalt", 9, 0.0085), + ("Schleswig-Holstein", 9, 0.0085), + ("Thüringen", 9, 0.0085)] + self.root = root - frame = Frame(root) + self.root.title("Lohnrechner 2007 - v%s" % _release_version) + + self.SetupUI() + self.UpdateLand() + self.InitSozv() + self.ResetInput() + + def SetupUI(self): + self.root.resizable(NO, NO) + + frame = Frame(self.root) frame.grid(padx=10, pady=10) - Label(frame, text="Lohn:").grid(row=0, sticky=E) + # Steuern Ein/Ausgabe + Label(frame, text="Geburtsjahr:").grid(row=0, sticky=E) + self.geb = Entry(frame) + self.geb.bind("", self.NewInput) + self.geb.grid(row=0, column=1, sticky=W) + + Label(frame, text="Lohn (monatlich):").grid(row=1, sticky=E) self.lohn = Entry(frame) self.lohn.bind("", self.NewInput) - self.lohn.grid(row=0, column=1, sticky=W) + self.lohn.grid(row=1, column=1, sticky=W) - Label(frame, text="Steuerklasse:").grid(row=1, sticky=E) + Label(frame, text="Steuerklasse:").grid(row=2, sticky=E) self.stkl = IntVar() stklframe = Frame(frame) - stklframe.grid(row=1, column=1, sticky=W) + stklframe.grid(row=2, column=1, sticky=W) for text, val in [("I", 1), ("II", 2), ("III", 3), @@ -69,39 +83,36 @@ ("V", 5), ("VI", 6)]: stklradio = Radiobutton(stklframe, text=text, value=val, - indicatoron=0, command=self.CalcOutput, + indicatoron=0, command=self.NewInput, variable=self.stkl) if text == "I": stklradio.select() stklradio.pack(side=LEFT) - Label(frame, text="Kirchensteuer:").grid(row=2, sticky=E) + Label(frame, text="Kirchensteuer:").grid(row=3, sticky=E) self.kirche = IntVar() - kircheradio = Checkbutton(frame, onvalue=1, offvalue=0, - command=self.CalcOutput, - variable=self.kirche).grid(row=2, column=1, sticky=W) + Checkbutton(frame, onvalue=1, offvalue=0, command=self.NewInput, + variable=self.kirche).grid(row=3, column=1,sticky=W) - Label(frame, text="Kinderfreibetrag:").grid(row=3, sticky=E) + Label(frame, text="Kinderfreibetrag:").grid(row=4, sticky=E) self.kfb = Entry(frame) self.kfb.bind("", self.NewInput) - self.kfb.grid(row=3, column=1, sticky=W) + self.kfb.grid(row=4, column=1, sticky=W) - Label(frame, text="Bundesland:").grid(row=4, sticky=E) + Label(frame, text="Bundesland:").grid(row=5, sticky=NE) landframe = Frame(frame) scrollbar = Scrollbar(landframe, orient=VERTICAL) - self.land = Listbox(landframe, height=4, selectmode=SINGLE, - yscrollcommand=scrollbar.set) + self.landbox = Listbox(landframe, height=4, selectmode=SINGLE, + yscrollcommand=scrollbar.set) for land in self.laender: - self.land.insert(END, land[0]) - self.land.select_set(0) - self.land.bind("", self.NewInput) - self.land.pack(side=RIGHT, fill=Y) - scrollbar.config(command=self.land.yview) + self.landbox.insert(END, land[0]) + self.landbox.select_set(0) + self.landbox.bind("<>", self.NewLandSel) + self.landbox.pack(side=RIGHT, fill=Y) + scrollbar.config(command=self.landbox.yview) scrollbar.pack(side=LEFT, fill=BOTH, expand=1) - landframe.grid(row=4, column=1, sticky=W) + landframe.grid(row=5, rowspan=4, column=1, sticky=W) - self.ResetInput() - Label(frame, text="Lohnsteuer:").grid(row=0, column=2, sticky=E) self.lst = Entry(frame) self.lst.grid(row=0, column=3, sticky=W) @@ -114,19 +125,85 @@ self.kist = Entry(frame) self.kist.grid(row=2, column=3, sticky=W) + Label(frame, text="Lohn nach Steuern:").grid(row=3, column=2, sticky=E) + self.netto1 = Entry(frame) + self.netto1.grid(row=3, column=3, sticky=W) + + # Sozialversicherung Ein/Ausgabe + Label(frame, text="Sozialversicherung:").grid(row=9, sticky=E) + self.sozv = IntVar() + sozvradio = Checkbutton(frame, onvalue=1, offvalue=0, + command=self.NewInput, variable=self.sozv) + sozvradio.select() + sozvradio.grid(row=9, column=1, sticky=W) + + Label(frame, text="Krankenkassenbeitrag:").grid(row=10, sticky=E) + self.kvsatz = Entry(frame) + self.kvsatz.bind("", self.NewInput) + self.kvsatz.grid(row=10, column=1, sticky=W) + + Label(frame, text="Krankenkassenzuschlag (0.9%):").grid(row=11, sticky=E) + self.kvsoli = IntVar() + kvsoliradio = Checkbutton(frame, onvalue=1, offvalue=0, + command=self.NewInput, variable=self.kvsoli) + kvsoliradio.select() + kvsoliradio.grid(row=11, column=1, sticky=W) + + + Label(frame, text="Rentenversicherung:").grid(row=4, column=2, sticky=E) + self.rv = Entry(frame) + self.rv.grid(row=4, column=3, sticky=W) + + Label(frame, text="Krankenversicherung:").grid(row=5, column=2, sticky=E) + self.kv = Entry(frame) + self.kv.grid(row=5, column=3, sticky=W) + + Label(frame, text="Arbeitslosenversicherung:").grid(row=6, column=2, + sticky=E) + self.av = Entry(frame) + self.av.grid(row=6, column=3, sticky=W) + + Label(frame, text="Pflegeversicherung:").grid(row=7, column=2, sticky=E) + self.pv = Entry(frame) + self.pv.grid(row=7, column=3, sticky=W) + + Label(frame, text="Netto Lohn:").grid(row=8, column=2, sticky=E) + self.netto2 = Entry(frame) + self.netto2.grid(row=8, column=3, sticky=W) + + # Allgemeine UI Elemente buttons = Frame(frame) - buttons.grid(row=4, column=2, columnspan=2) - Button(buttons, text="Quit", command=root.quit).pack(side=LEFT) + buttons.grid(row=10, column=2, rowspan=2, columnspan=2) + Button(buttons, text="Quit", command=self.root.quit).pack(side=LEFT) Button(buttons, text="Info", command=self.Info).pack(side=LEFT) Button(buttons, text="Berechnen", command=self.CalcOutput).pack(side=LEFT) - + + def NewInput(self, event=0): + # Es ist möglich alle Einträge in der Listbox zu deselektieren, + # es ist aber immer genau ein Eintrag aktuell, darum wird er ggf. + # zwangsselektiert: + # FIX ME: eigendlich wäre das ein Fall für ein custom widget! + if len(self.landbox.curselection()) == 0: + self.landbox.select_set(self.land) self.CalcOutput() - def NewInput(self, event): + def UpdateLand(self): + self.land = int(self.landbox.curselection()[0]) + + def NewLandSel(self, event=0): + self.UpdateLand() self.CalcOutput() def ResetInput(self): + self.ResetInputGeb() self.ResetInputLohn() + self.ResetInputKfb() + self.ResetInputKVsatz() + self.NewLandSel() + + def ResetInputGeb(self): + self.geb.delete(0, END) + self.geb.insert(0, "1964") def ResetInputLohn(self): self.lohn.delete(0, END) @@ -136,6 +213,10 @@ self.kfb.delete(0, END) self.kfb.insert(0, "0") + def ResetInputKVsatz(self): + self.kvsatz.delete(0, END) + self.kvsatz.insert(0, "13.8") + def InitCalc(self): try: self.SetLohn(float(self.lohn.get())) @@ -143,41 +224,113 @@ self.ResetInputLohn() try: + self.SetGeb(int(self.geb.get())) + except: + self.ResetInputGeb() + + try: self.SetKinderfreibetrag(float(self.kfb.get())) except: self.ResetInputKfb() + try: + self.SetKV(float(self.kvsatz.get())) + except: + self.ResetInputKVsatz() + self.SetSteuerklasse(self.stkl.get()) - self.SetKirchensteuer(self.kirche.get() * - self.laender[int(self.land.curselection()[0])][1]) + self.SetKirchensteuerProzent(self.kirche.get() * + self.laender[self.land][1]) def CalcOutput(self): self.InitCalc() self.Calc() self.lst.delete(0, END) - self.lst.insert(0, "%.2f" % self.GetLohnsteuer()) + self.lst.insert(0, "%.2f" % self.GetLohnsteuer()) self.soli.delete(0, END) - self.soli.insert(0, "%.2f" % self.GetSoli()) + self.soli.insert(0, "%.2f" % self.GetSoli()) self.kist.delete(0, END) - self.kist.insert(0, "%.2f" % self.GetKirchensteuer()) + self.kist.insert(0, "%.2f" % self.GetKirchensteuer()) + netto1 = self.GetLohn() - self.GetLohnsteuer() \ + - self.GetSoli() - self.GetKirchensteuer() + self.netto1.delete(0, END) + self.netto1.insert(0, "%.2f" % netto1) + self.rv.delete(0, END) + self.rv.insert(0, "%.2f" % self.GetRV()) + self.pv.delete(0, END) + self.pv.insert(0, "%.2f" % self.GetPV()) + self.av.delete(0, END) + self.av.insert(0, "%.2f" % self.GetAV()) + self.kv.delete(0, END) + self.kv.insert(0, "%.2f" % self.GetKV()) + netto2 = netto1 - self.GetRV() - self.GetAV() \ + - self.GetPV() - self.GetKV() + self.netto2.delete(0, END) + self.netto2.insert(0, "%.2f" % netto2) def Info(self): infowin = Toplevel(self.root) infowin.title("Info") - Label(infowin, text="Lohnrechner 2005 v%s" % _release_version, + Label(infowin, text="Lohnrechner 2007 v%s" % _release_version, font=("Times", 14, "bold italic")).grid(row=0, pady=20) Label(infowin, text= - "Copyright (C) 2005 Intevation GmbH \n\n\ -Lohnrechner 2005 comes with ABSOLUTELY NO WARRANTY.\n\ + "Copyright (C) 2005,2006,2007 Intevation GmbH \n\n\ +Lohnrechner 2007 comes with ABSOLUTELY NO WARRANTY.\n\ This is free software, and you are welcome to redistribute it\n\ under the terms of the GNU General Public License.\n\ For more information about these matters, see the file named COPYING.\n\n\ -Dieses Programm verwendet LST2005 %s" % LST2005._ModulVersion()).grid(row=1, padx=10) +Dieses Programm verwendet LST2007 %s" % LST2007._ModulVersion()).grid(row=1, padx=10) Button(infowin, text="Ok", command=infowin.destroy).grid(row=2, pady=10) + # + # Funktionen zur Berechnung der Sozialversicherungsbeiträge. + # + # FIX ME: Dieser Teil könnte evl. in ein eigenes Modul ausgelagert werden. + # + + def InitSozv(self): + self.AVsatz = 0.042 / 2 + self.RVsatz = 0.199 / 2 + # PVsatz ist in self.laender definiert! + self.PVkinderlose = 0.0025 + self.BMG1 = 3562.5 + self.BMG2 = 5250 + + def SetKV(self, value): + assert value >= 0.0 and value <= 100.0, \ + "must be in range 0.0-100.0 (Percent)" + self.KVsatz = (value / 100.0) + + def GetAV(self): + lohn = self.GetLohn() + if lohn > self.BMG2 : lohn = self.BMG2 + return round(self.sozv.get() * self.AVsatz * lohn, 2) + + def GetRV(self): + lohn = self.GetLohn() + if lohn > self.BMG2 : lohn = self.BMG2 + return round(self.sozv.get() * self.RVsatz * lohn, 2) + + def GetPV(self): + self.PVsatz = self.laender[self.land][2] + lohn = self.GetLohn() + if lohn > self.BMG1 : lohn = self.BMG1 + PV = self.PVsatz * lohn + if float(self.kfb.get()) == 0.0 : + PV += lohn * self.PVkinderlose + return round(self.sozv.get() * PV, 2) + + def GetKV(self): + self.KVsoli = self.kvsoli.get() + lohn = self.GetLohn() + if lohn > self.BMG1 : lohn = self.BMG1 + if self.KVsoli : + return round(self.sozv.get() * ((self.KVsatz / 2) + 0.009) * lohn, 2) + else : + return round(self.sozv.get() * self.KVsatz * lohn / 2, 2) + if __name__ == "__main__": root = Tk() lr = Lohnrechner(root) root.mainloop() -