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

Contents of /trunk/RCS/LST2005.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations)
Tue Jan 11 17:10:26 2005 UTC (20 years, 3 months ago) by wilde
File MIME type: text/x-python
File size: 18508 byte(s)
Letzte Subprogramme aus dem Programmablaufplan hinzugef�gt
Sch�ne API in eigene Klasse gesteckt

1 # --------------------------------------------------------------------
2 # LST2005 -- Python Modul zur Berechnung der Deutschen Lohnsteuer 2005
3 # $Id$
4 # --------------------------------------------------------------------
5 #
6 # Copyright (c) 2005 by Intevation GmbH
7 # Authors:
8 # Sascha Wilde <[email protected]>
9 #
10 # This program is free software under the GPL (>=v2)
11 # Read the file COPYING coming with this package for details.
12
13 """Lohnsteuerberechnung nach dem offiziellen Programmablaufplan
14 wie in Programmablaufplan-LSt.pdf dokumentiert."""
15
16 # Die Variablen Namen sind hässlich, die Algorithmen nicht
17 # dokumentiert, der Code grausam -- dafür entspricht alles Zeile für
18 # Zeile obigem Dokument. Jedenfalls sollte es so sein...
19
20 from math import ceil, floor
21
22 # Wir brauchen eigene Rundungsfunktionen mit definierter Präzision
23 def FixedPointFloor(value, precision=2):
24 i = 10.0 ** precision
25 return floor(value * i) / i
26
27 def FixedPointCeil(value, precision=2):
28 i = 10.0 ** precision
29 return ceil(value * i) / i
30
31 # Ein paar Konstanten um das ganze etwas Benutzbarer zu machen:
32 JAHR = 1
33 MONAT = 2
34 WOCHE = 3
35 TAG = 4
36 I = 1
37 II = 2
38 III = 3
39 IV = 4
40 V = 5
41 VI = 6
42
43 class LST:
44 def __init__(self,
45 RE4=0,
46 ALTER1=0,
47 HINZUR=0,
48 JFREIB=0,
49 JHINZU=0,
50 JRE4 =0,
51 JVBEZ =0,
52 KRV =0,
53 LZZ =2,
54 R =0,
55 SONSTB=0,
56 STKL =1,
57 VBEZ =0,
58 VBEZM =0,
59 VBEZS =0,
60 VBS =0,
61 VMT =0,
62 WFUNDF=0,
63 ZKF =0,
64 ZMVB =0):
65 self.Set_RE4(RE4)
66 self.Set_ALTER1(ALTER1)
67 self.Set_HINZUR(HINZUR)
68 self.Set_JFREIB(JFREIB)
69 self.Set_JHINZU(JHINZU)
70 self.Set_JRE4(JRE4)
71 self.Set_JVBEZ(JVBEZ)
72 self.Set_KRV(KRV)
73 self.Set_LZZ(LZZ)
74 self.Set_R(R)
75 self.Set_SONSTB(SONSTB)
76 self.Set_STKL(STKL)
77 self.Set_VBEZ(VBEZ)
78 self.Set_VBEZM(VBEZM)
79 self.Set_VBEZS(VBEZS)
80 self.Set_VBS(VBS)
81 self.Set_VMT(VMT)
82 self.Set_WFUNDF(WFUNDF)
83 self.Set_ZKF(ZKF)
84 self.Set_ZMVB(ZMVB)
85 # Vorgegebene Ausgangsparameter
86 self.BK = 0
87 self.BKS = 0
88 self.BKV = 0
89 self.LSTLZZ = 0
90 self.SOLZLZZ = 0
91 self.SOLZS = 0
92 self.SOLZV = 0
93 self.STS = 0
94 self.STV = 0
95
96 def Calc(self):
97 """Berechnet die Lohnsteuer,
98 setzt BK, BKS, BKV, LSTLZZ, SOLZLZZ, SOLZS, SOLZV, STS und STV"""
99 # Interne Felder
100 # Laut Dokumentation sollen diese vor der Berechnung gelöscht werden,
101 # es ist mir nicht klar, ob das wirklich nötig ist...
102 self._ALTE = 0
103 self._ANP = 0
104 self._ANTEIL1 = 0
105 self._ANTEIL2 = 0
106 self._BMG = 0
107 self._DIFF = 0
108 self._EFA = 0
109 self._FVB = 0
110 self._FVBZ = 0
111 self._JBMG = 0
112 self._JW = 0
113 self._KENNZ = 0
114 self._KFB = 0
115 self._KZTAB = 1
116 self._LSTJAHR = 0
117 self._LST1 = 0
118 self._LST2 = 0
119 self._LST3 = 0
120 self._MIST = 0
121 self._RE4LZZ = 0
122 self._RE4LZZV = 0
123 self._RW = 0.0
124 self._SAP = 0
125 self._SOLZFREI = 0
126 self._SOLZJ = 0.0 # 2 Dezimalstellen
127 self._SOLZMIN = 0.0 # 2 Dezimalstellen
128 self._ST = 0
129 self._ST1 = 0
130 self._ST2 = 0
131 self._VBEZB = 0
132 self._VHB = 0
133 self._VSP = 0.0 # 2 Dezimalstellen
134 self._VSPN = 0
135 self._VSP1 = 0.0 # 2 Dezimalstellen
136 self._VSP2 = 0.0 # 2 Dezimalstellen
137 self._VSPKURZ = 0
138 self._VSPMAX1 = 0
139 self._VSPMAX2 = 0
140 self._VSPO = 0.0 # 2 Dezimalstellen
141 self._VSPREST = 0.0 # 2 Dezimalstellen
142 self._VSPVOR = 0.0 # 2 Dezimalstellen
143 # Jetzt wirds richtig toll: X und Y
144 # kann mal bitte jemand den Verantwortlichen für diese
145 # Variablen Namen schlagen?
146 self._X = 0.0 # 2 Dezimalstellen
147 self._Y = 0.0 # 6 Dezimalstellen
148 self._ZRE4 = 0.0 # 2 Dezimalstellen
149 self._ZRE4VP = 0.0 # 2 Dezimalstellen
150 self._ZRE4VP1 = 0.0 # 2 Dezimalstellen
151 self._ZTABFB = 0
152 self._ZVE = 0
153 self._ZX = 0
154 self._ZZX = 0
155 self._HOCH = 0
156 self._VERGL = 0
157 # ------------------------------------------------------------
158 # Anfang der Berechnung
159 self._MRE4LZZ()
160 self._RE4LZZ = self.RE4 - self._FVB \
161 - self._ALTE - self.WFUNDF \
162 + self.HINZUR
163 self._RE4LZZV = self.RE4 - self._FVB - self._ALTE
164 self._MRE4()
165 self._MZTABFB()
166 self._MLSTJAHR()
167 self._LSTJAHR = self._ST
168 self._JW = self._LSTJAHR * 100
169 self._UPANTEIL()
170 self.LSTLZZ = self._ANTEIL1
171 if self.ZKF > 0:
172 self._ZTABFB += self._KFB
173 self._MLSTJAHR()
174 self._JBMG = self._ST
175 else:
176 self._JBMG = self._LSTJAHR
177 self._MSOLZ()
178 self._MSONST()
179 self._MVMT()
180
181 # Benutzte Unterprogramme:
182 def _MRE4LZZ(self):
183 if self.VBEZ == 0:
184 self._FVBZ = 0
185 self._FVB = 0
186 else:
187 if self.LZZ == 1:
188 self._VBEZB = self.VBEZM * self.ZMVB + self.VBEZS
189 self._FVBZ = 75 * self.ZMVB
190 else:
191 self._VBEZB = self.VBEZM * 12 + self.VBEZS
192 self._FVBZ = 900
193 self._FVB = ceil(self._VBEZB * 0.4)
194 if self._FVB > 300000:
195 self._FVB = 300000
196 self._JW = self._FVB
197 self._UPANTEIL()
198 self._FVB = self._ANTEIL2
199 if self.ALTER1 == 0:
200 self._ALTE = 0
201 else:
202 self._BMG = self.RE4 - self.VBEZ
203 self._ALTE = ceil(self._BMG * 0.4)
204 self._JW = 190000
205 self._UPANTEIL()
206 if self._ALTE > self._ANTEIL2:
207 self._ALTE = self._ANTEIL2
208
209 def _MRE4(self):
210 if self.LZZ == 1:
211 self._ZRE4 = FixedPointFloor(self._RE4LZZ / 100.0)
212 self._ZRE4VP = FixedPointFloor(self._RE4LZZV / 100.0)
213 elif self.LZZ == 2:
214 self._ZRE4 = FixedPointFloor((self._RE4LZZ + 0.67) * 0.12)
215 self._ZRE4VP = FixedPointFloor((self._RE4LZZV + 0.67) * 0.12)
216 elif self.LZZ == 3:
217 self._ZRE4 = FixedPointFloor((self._RE4LZZ + 0.89) * 3.6 / 7)
218 self._ZRE4VP = FixedPointFloor((self._RE4LZZV + 0.89) * 3.6 / 7)
219 else:
220 self._ZRE4 = FixedPointFloor((self._RE4LZZ + 0.56) * 3.6)
221 self._ZRE4VP = FixedPointFloor((self._RE4LZZV + 0.56) * 3.6)
222 if self._ZRE4 < 0:
223 self._ZRE4 = 0.0
224
225 def _MZTABFB(self):
226 self._KZTAB = 1
227 if self.STKL < 6:
228 if self.VBEZ > 0:
229 self._ANP = 102
230 if self.RE4 > self.VBEZ:
231 self._ANP += 920
232 else:
233 self._ANP = 0
234 if self.STKL == 1:
235 self._SAP = 36
236 self._KFB = self.ZKF * 5808
237 elif self.STKL == 2:
238 self._EFA = 1308
239 self._SAP = 36
240 self._KFB = self.ZKF * 5808
241 elif self.STKL == 3:
242 self._KZTAB = 2
243 self._SAP = 72
244 self._KFB = self.ZKF * 5808
245 elif self.STKL == 4:
246 self._SAP = 36
247 self._KFB = self.ZKF * 2904
248 else:
249 self._KFB = 0
250 self._ZTABFB = self._EFA + self._ANP + self._SAP + self._FVBZ
251 self._KENNZ = 0
252
253 def _MLSTJAHR(self):
254 if self.STKL < 5:
255 self._UPEVP()
256 else:
257 self._VSP = 0.0
258 self._ZVE = self._ZRE4 - self._ZTABFB - self._VSP
259 if self._ZVE < 1:
260 self._ZVE = self._X = 0.0
261 else:
262 self._X = floor(float(self._ZVE) / self._KZTAB)
263 if self.STKL < 5:
264 self._UPTAB05()
265 else:
266 self._MST5_6()
267
268 def _UPEVP(self):
269 if self.KRV == 1:
270 self._VSP1 = 1.0
271 else:
272 if self._ZRE4VP > 62400:
273 self._ZRE4VP = 62400.0
274 self._VSP1 = 0.2 * self._ZRE4VP
275 self._VSP1 = self._VSP1 * 0.0975
276 self._VSP2 = 0.11 * self._ZRE4VP
277 self._VHB = 1500 * self._KZTAB
278 if self._VSP2 > self._VHB:
279 self._VSP2 = self._VHB
280 self._VSPN = ceil(self._VSP1 + self._VSP2)
281 self._MVSP()
282 if self._VSPN > self._VSP:
283 self._VSP = self._VSPN
284
285 def _MVSP(self):
286 self._VSPO = self._ZRE4VP * 0.2
287 self._VSPVOR = 3068 * self._KZTAB
288 self._VSPMAX1 = 1334 * self._KZTAB
289 self._VSPMAX2 = 667 * self._KZTAB
290 self._VSPKURZ = 1134 * self._KZTAB
291 if self.KRV == 1:
292 if self._VSPO > self._VSPKURZ:
293 self._VSP = self._VSPKURZ
294 else:
295 self._VSP = ceil(self._VSPO)
296 else:
297 self._UMVSP()
298
299 def _UMVSP(self):
300 if self._KENNZ == 1:
301 self._VSPVOR = self._VSPVOR - self._ZRE4VP1 * 0.16
302 else:
303 self._VSPVOR = self._VSPVOR - self._ZRE4VP * 0.16
304 if self._VSPVOR < 0:
305 self._VSPVOR = 0.0
306 if self._VSPO > self._VSPVOR:
307 self._VSP = self._VSPVOR
308 self._VSPREST = self._VSPO - self._VSPVOR
309 if self._VSPREST > self._VSPMAX1:
310 self._VSP += self._VSPMAX1
311 self._VSPREST = FixedPointCeil((self._VSPREST - self._VSPMAX1) / 2.0)
312 if self._VSPREST > self._VSPMAX2:
313 self._VSP = ceil(self._VSP + self._VSPMAX2)
314 else:
315 self._VSP = ceil(self._VSP + self._VSPREST)
316 else:
317 self._VSP = ceil(self._VSP + self._VSPREST)
318 else:
319 self._VSP = ceil(self._VSPO)
320
321 def _MST5_6(self):
322 self._ZZX = self._X
323 if self._ZZX > 25812:
324 self._ZX = 25812
325 self._UP5_6()
326 self._ST = floor(self._ST + (self._ZZX - 25812) * 0.42)
327 else:
328 self._ZX = self._ZZX
329 self._UP5_6()
330 if self._ZZX > 9144:
331 self._VERGL = self._ST
332 self._ZX = 9144
333 self._UP5_6()
334 self._HOCH = floor(self._ST + (self._ZZX - 9144) * 0.42)
335 if self._HOCH < self._VERGL:
336 self._ST = self._HOCH
337 else:
338 self._ST = self._VERGL
339
340 def _UP5_6(self):
341 self._X = self._ZX * 1.25
342 self._UPTAB05()
343 self._ST1 = self._ST
344 self._X = self._ZX * 0.75
345 self._UPTAB05()
346 self._ST2 = self._ST
347 self._DIFF = (self._ST1 - self._ST2) * 2
348 self._MIST = floor(self._ZX * 0.15)
349 if self._MIST > self._DIFF:
350 self._ST = self._MIST
351 else:
352 self._ST = self._DIFF
353
354 def _MSOLZ(self):
355 self._SOLZFREI = 972 * self._KZTAB
356 if self._JBMG > self._SOLZFREI:
357 self._SOLZJ = FixedPointFloor(self._JBMG * 5.5 / 100.0)
358 self._SOLZMIN = (self._JBMG - self._SOLZFREI) * 20 / 100.0
359 if self._SOLZMIN < self._SOLZJ:
360 self._SOLZJ = self._SOLZMIN
361 self._JW = self._SOLZJ * 100
362 self._UPANTEIL()
363 self.SOLZLZZ = self._ANTEIL1
364 else:
365 self.SOLZLZZ = 0
366 if self.R > 0:
367 self._JW = self._JBMG * 100
368 self._UPANTEIL
369 self.BK = self._ANTEIL1
370 else:
371 self.BK = 0
372
373 def _UPANTEIL(self):
374 if self.LZZ == 1:
375 self._ANTEIL1 = self._JW
376 self._ANTEIL2 = self._JW
377 elif self.LZZ == 2:
378 self._ANTEIL1 = floor(self._JW / 12.0)
379 self._ANTEIL2 = ceil(self._JW / 12.0)
380 elif self.LZZ == 3:
381 self._ANTEIL1 = floor(self._JW * 7 / 360.0)
382 self._ANTEIL2 = ceil(self._JW * 7 / 360.0)
383 else:
384 self._ANTEIL1 = floor(self._JW / 360.0)
385 self._ANTEIL2 = ceil(self._JW / 360.0)
386
387 def _UPTAB05(self):
388 if self._X < 7665:
389 self._ST = 0
390 elif self._X < 12740:
391 self._Y = (self._X - 7664) / 10000.0
392 self._RW = self._Y * 883.74
393 self._RW += 1500
394 self._ST = floor(self._RW * self._Y)
395 elif self._X < 52152:
396 self._Y = (self._X - 12739) / 10000.0
397 self._RW = self._Y * 228.74
398 self._RW += 2397
399 self._RW *= self._Y
400 self._ST = floor(self._RW + 989)
401 else:
402 self._ST = floor(self._X * 0.42 - 7914)
403 self._ST *= self._KZTAB
404
405 def _MSONST(self):
406 if self.SONSTB > 0:
407 # ------------------------------
408 # Nicht im offiziellen Programm-
409 # ablaufplan: Attribute sichern
410 old_lzz = self.LZZ
411 old_vbez = self.VBEZ
412 old_re4 = self.RE4
413 # ------------------------------
414 self.LZZ = 1
415 self.VBEZ = self.JVBEZ
416 self.RE4 = self.JRE4
417 self._MRE4LZZ()
418 self._MRE4LZZ2()
419 self._MRE4()
420 self._MZTABFB()
421 self._MLSTJAHR()
422 self._LST1 = self._ST * 100
423 self.VBEZ = self.JVBEZ + self.VBS
424 self.RE4 = self.JRE4 + self.SONSTB
425 self._MRE4LZZ()
426 self._MRE4LZZ2()
427 self._MRE4()
428 self._MLSTJAHR()
429 self._LST2 = self._ST * 100
430 self.STS = self._LST2 - self._LST1
431 self.SOLZS = self.STS * 5.5 / 100
432 if self.R > 0:
433 self.BKS = self.STS
434 else:
435 self.BKS = 0
436 # ------------------------------
437 # Nicht im offiziellen Programm-
438 # ablaufplan: Attribute
439 # wiederherstellen
440 self.LZZ = old_lzz
441 self.VBEZ = old_vbez
442 self.RE4 = old_re4
443 # ------------------------------
444 else:
445 self.STS = 0
446 self.SOLZS = 0
447 self.BKS = 0
448
449 def _MRE4LZZ2(self):
450 self._RE4LZZ = self.RE4 - self._FVB - self._ALTE \
451 - self.JFREIB + self.JHINZU
452 self._RE4LZZV = self.RE4 - self._FVB - self._ALTE
453
454 def _MVMT(self):
455 if self.VMT > 0:
456 # ------------------------------
457 # Nicht im offiziellen Programm-
458 # ablaufplan: Attribute sichern
459 old_lzz = self.LZZ
460 old_vbez = self.VBEZ
461 old_re4 = self.RE4
462 # ------------------------------
463 self.LZZ = 1
464 self.VBEZ = self.JVBEZ + self.VBS
465 self.RE4 = self.JRE4 + self.SONSTB
466 self._MRE4LZZ()
467 self._MRE4LZZ2()
468 self._MRE4()
469 self._MZTABFB()
470 self._MLSTJAHR()
471 self._LST1 = self._ST * 100
472 self.RE4 = self.JRE4 + self.SONSTB + self.VMT
473 self._MRE4LZZ()
474 self._MRE4LZZ2()
475 self._MRE4()
476 self._KENNZ = 1
477 self._ZRE4VP1 = self._ZRE4VP
478 self._MLSTJAHR()
479 self._LST3 = self._ST * 100
480 self.RE4 = self.JRE4 + self.SONSTB
481 self._MRE4LZZ()
482 self.RE4 = self.JRE4 + self.SONSTB + self.VMT / 5
483 self._MRE4LZZ2()
484 self._MRE4()
485 self._MLSTJAHR()
486 self._LST2 = self._ST * 100
487 self.STV = (self._LST2 - self.LST1) * 5
488 self._LST3 -= self._LST1
489 if self._LST3 < self.STV:
490 self.STV = self._LST3
491 self.SOLZV = floor(self.STV * 5.5 / 100)
492 if self.R > 0:
493 self.BKV = self.STV
494 else:
495 self.BKV = 0
496 # ------------------------------
497 # Nicht im offiziellen Programm-
498 # ablaufplan: Attribute
499 # wiederherstellen
500 self.LZZ = old_lzz
501 self.VBEZ = old_vbez
502 self.RE4 = old_re4
503 # ------------------------------
504 else:
505 self.STV = 0
506 self.SOLZV = 0
507 self.BKV = 0
508
509 # Methoden zum geprüften setzen der Wert
510 # FIX ME: Prüfung _sehr_ unvollständig
511 def Set_RE4(self, value):
512 assert value >= 0, "must not be negative"
513 self.RE4 = value
514
515 def Set_ALTER1(self, value):
516 assert value in (0,1), "must be 0 or 1"
517 self.ALTER1 = value
518
519 def Set_HINZUR(self, value):
520 self.HINZUR = value
521
522 def Set_JFREIB(self, value):
523 self.JFREIB = value
524
525 def Set_JHINZU(self, value):
526 self.JHINZU = value
527
528 def Set_JRE4(self, value):
529 self.JRE4 = value
530
531 def Set_JVBEZ(self, value):
532 self.JVBEZ = value
533
534 def Set_KRV(self, value):
535 if value not in (0,1):
536 raise ValueError
537 self.KRV = value
538
539 def Set_LZZ(self, value):
540 assert value in (1,2,3,4), "must be in range 1-4 (JAHR, MONAT, WOCHE, TAG)"
541 self.LZZ = value
542
543 def Set_R(self, value):
544 self.R = value
545
546 def Set_SONSTB(self, value):
547 self.SONSTB = value
548
549 def Set_STKL(self, value):
550 assert value in (1,2,3,4,5,6), "must be in range 1-6 (I II III IV V VI)"
551 self.STKL = value
552
553 def Set_VBEZ(self, value):
554 self.VBEZ = value
555
556 def Set_VBEZM(self, value):
557 self.VBEZM = value
558
559 def Set_VBEZS(self, value):
560 self.VBEZS = value
561
562 def Set_VBS(self, value):
563 self.VBS = value
564
565 def Set_VMT(self, value):
566 self.VMT = value
567
568 def Set_WFUNDF(self, value):
569 self.WFUNDF = value
570
571 def Set_ZKF(self, value):
572 self.ZKF = value
573
574 def Set_ZMVB(self, value):
575 self.ZMVB = value
576
577 # --------------------------------------------------------------------
578 # Eine etwas schönere API:
579 #
580
581 class LStRechner2005(LST):
582 def __init__(self):
583 LST.__init__(self)
584
585 def SetLohn(self, lohn):
586 self.Set_RE4(lohn * 100.0)
587
588 def SetZeitraum(self, lzz):
589 self.Set_LZZ(lzz)
590
591 def SetSteuerklasse(self, stkl):
592 self.Set_STKL(stkl)
593
594 def GetLohnsteuer(self):
595 return round(self.LSTLZZ / 100, 2)

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26