// JavaScript-Programm nach dem Programmablaufplan für die maschinelle Berechnung
// der vom Arbeitslohn einzubehaltenden Lohnsteuer, des Solidrätätszuschlags und
// der Maßstabsteuer für die Kirchenlohnsteuer 2009
// Version 15.3.2009
// Der für 2009 geänderte Programmablaufplan (vm 4.3.2009) findet sich auf den Internetseiten des BMF zum
// Herunterladen unter
// http://www.bundesfinanzministerium.de/nn_304/DE/BMF__Startseite/Aktuelles/BMF__Schreiben/Veroffentlichungen__zu__Steuerarten/lohnsteuer/015__c,templateId=raw,property=publicationFile.pdf

public class lohnst_pap2009 {   // Interne Felder, PAP 2009, S. 6ff.

    String s;
    double ALTE;
    double ANP;
    double ANTEIL1;
    double ANTEIL2;
    double BMG;
    double DIFF;
    double EFA;
    double FVB;
    double FVBSO;
    double FVBZ;
    double FVBZSO;

    double HBALTE;
    double HFVB;
    double HFVBZ;
    double HFVBZSO;
    double JLFREIB;
    double JLHINZU;
    int J;
    double JBMG;
    double JW;
    int K;
    int KENNVMT;
    double KFB;
    int KZTAB;
    double LSTJAHR;
    double LST1;
    double LST2;
    double LST3;
    double LSTSO;
    double LSTOSO;
    double MIST;
    double RW;
    double SAP;
    double SOLZFREI;
    double SOLZJ;
    double SOLZMIN;
    double ST;
    double ST1;
    double ST2;
    double STOVMT;
    // Definition TAB1 usw. s. unten
    double VBEZB;
    double VBEZBSO;
    double VBEZSO;
    double VHB;
    double VSP;
    double VSPN;
    double VSP1;
    double VSP2;
    double VSPKURZ;
    double VSPMAX1;
    double VSPMAX2;
    double VSPO;
    double VSPREST;
    double VSPVOR;
    double X;
    double Y;
    double ZRE4;
    double ZRE4J;


    double ZRE4VP;
    double ZTABFB;

    double ZVBEZ;
    double ZVBEZJ;
    double ZVE;
    double ZX;
    double ZZX;
    double HOCH;
    double VERGL;

    double TAB1[] = {0, 0.4, 0.384, 0.368, 0.352, 0.336, 0.32, 0.304, 0.288, 0.272, 0.256, 0.24, 0.224, 0.208, 0.192, 0.176, 0.16, 0.152, 0.144, 0.136, 0.128, 0.12, 0.112, 0.104, 0.096, 0.088, 0.08, 0.072, 0.064, 0.056, 0.048, 0.04, 0.032, 0.024, 0.016, 0.008, 0};
   int TAB2[] = {0, 3000, 2880, 2760, 2640, 2520, 2400, 2280, 2160, 2040, 1920, 1800, 1680, 1560, 1440, 1320, 1200, 1140, 1080, 1020, 960, 900, 840, 780, 720, 660, 600, 540, 480, 420, 360, 300, 240, 180, 120, 60, 0};
    int TAB3[]= {0, 900, 864, 828, 792, 756, 720, 684, 648, 612, 576, 540, 504, 468, 432, 396, 360, 342, 324, 306, 288, 270, 252, 234, 216, 198, 180, 162, 144, 126, 108, 90, 72, 54, 36, 18, 0};
    //TAB4 = TAB1
    int TAB5[] = {0,1900, 1824, 1748, 1672, 1596, 1520, 1444, 1368, 1292, 1216, 1140, 1064, 988, 912, 836, 760, 722, 684, 646, 608, 570, 532, 494, 456, 418, 380, 342, 304, 266, 228, 190, 152, 114, 76, 38, 0};

    // --- Eingangsparameter  PAP 2009, S. 3ff.

    int AJAHR;
    int ALTER1;  //Unnötige Konstante, da Alter mit AJAHR bestimmt ist
    double LZZHINZU;
    double JFREIB;
    double JHINZU;
    double JRE4;
    double JVBEZ;
    int KRV;
    int LZZ;
    int R;
    double RE4;
    double SONSTB;
    double STERBE;
    int STKL;
    double VBEZ;
    double VBEZM;
    double VBEZS;
    double VBS;
    int VJAHR;
    double VKAPA;
    double VMT;
    double LZZFREIB;
    double ZKF;
    int ZMVB;

    // --- Ausgangsparameter, PAP 2009, S. 5

    double BK;
    double BKS;
    double BKV;
    double LSTLZZ;
    double SOLZLZZ;
    double SOLZS;
    double SOLZV;
    double STS;
    double STV;

    // --- EIGENE PARAMETER
    double lstges;
    double soliges;
    double kistges;


  public lohnst_pap2009(int i,int j,double d1,double d2,double d3,
           double d4,double d5,int k,int l,int m,double d6,double d7,
           double d8,int n,double d9,double d10,double d11,double d12,int o,
           double d13,double d14,double d15,double d16,int p) {

   // Parameter-Eingabe
    AJAHR = i;
    ALTER1 = j;
    LZZHINZU = d1;
    JFREIB = d2;
    JHINZU = d3;
    JRE4 = d4;
    JVBEZ = d5;
    KRV = k;
    LZZ = l;
    R = m;
    RE4 = d6;
    SONSTB = d7;
    STERBE = d8;
    STKL = n;
    VBEZ = d9;
    VBEZM = d10;
    VBEZS = d11;
    VBS = d12;
    VJAHR = o;
    VKAPA = d13;
    VMT = d14;
    LZZFREIB = d15;
    ZKF = d16;
    ZMVB = p;

    //Programmablaufplan 2009, Steuerung S.10

    MRE4JL();
    VBEZSO = 0;
    MRE4();
    MRE4ABZ();
    MZTABFB();
    KENNVMT = 0;
    MLSTJAHR();
    LSTJAHR = ST;
    JW = LSTJAHR * 100;
    UPANTEIL();
    LSTLZZ = ANTEIL1;
    if (ZKF > 0) {
       ZTABFB = ZTABFB + KFB;
       MLSTJAHR();
       JBMG = ST;
     }
     else
       JBMG = LSTJAHR;
    MSOLZ();
    MSONST();
    MVMT();


    // ---- Ausgabewerte für Übergabe an JavaScript-Programm festlegen -------------

    lstges = LSTLZZ + STS + STV;
    soliges = SOLZLZZ + SOLZS + SOLZV;
    kistges = BK + BKS + BKV;



    s = "FVB: " + FVB + " | FVBZ: " + FVBZ + " | ALTE: " + ALTE + " | ZTABFB: " + ZTABFB + " | VSP: " + VSP + " | LSTLZZ: " + LSTLZZ/100 + " | LSTSO: " + LSTSO/100;
    if(SONSTB > 0)
     s = s + " | LSTOSO: " + LSTOSO/100 + " |STS: " + STS/100;
    if(VMT > 0)
     s  = s + " | STV: " + STV/100 + " | LST1: " + LST1/100 + " | LST2: " + LST2/100 + " | LST3: " + LST3/100;

 }

  public void MRE4JL() {
 //Ermittlung des Jahresarbeitslohns und der Freibeträge, PAP 2009, S. 11

      JLFREIB = JFREIB /100;
      JLHINZU = JHINZU / 100;

    if (LZZ == 1) {
       ZRE4J = RE4 / 100;
       ZVBEZJ = VBEZ / 100;
       //JLFREIB = LZZFREIB /100;
       //JLHINZU = LZZHINZU / 100;
    }
    if (LZZ == 2) {
       ZRE4J = (RE4 * 12) /100;
       ZVBEZJ = (VBEZ * 12) /100;
       //JLFREIB = (LZZFREIB * 12) /100;
       //JLHINZU = (LZZHINZU * 12) / 100;
    }
    if (LZZ == 3) {
       ZRE4J = (RE4 * 360 / 7) /100;
       ZVBEZJ = (VBEZ * 360 / 7) /100;
       //JLFREIB = (LZZFREIB * 360 / 7) /100;
       //JLHINZU = (LZZHINZU * 360 / 7) / 100;
    }
    if (LZZ == 4) {
       ZRE4J = (RE4 * 360) /100;
       ZVBEZJ = (VBEZ * 360) /100;
       //JLFREIB = (LZZFREIB * 360) /100;
       //JLHINZU = (LZZHINZU * 360) / 100;
    }
    if (ZRE4J < 0)             // NICHT IM PAP
        ZRE4J = 0;

    if (ZVBEZJ <=0 || VBEZ<=0)
        ZVBEZJ = 0;
}

  public void MRE4() {
  // Freibetraege fuer Versorgungsbezuege, Altersentlastungsbetrag (§39b Abs. 2 Satz 3 EStG) PAP Seite 12

    if (ZVBEZJ == 0) {
       FVBZ = 0;
       FVB = 0;
       FVBZSO = 0;
       FVBSO = 0;
       }
      else {
       if (VJAHR < 2006)
          J = 1;
        else {
          if (VJAHR < 2040)
             J = VJAHR - 2004;
          else
             J = 36;
        }
       }
       if (LZZ == 1) {
             VBEZB = VBEZM * ZMVB + VBEZS;
             HFVB = TAB2[J];
             FVBZ = TAB3[J];
          }
            else {
             VBEZB = VBEZM * ZMVB + VBEZS;
             HFVB = (TAB2[J] / 12) * ZMVB;
             FVBZ = Math.ceil((TAB3[J] / 12) * ZMVB);
          }

       FVB = Math.ceil(VBEZB * TAB1[J])/100;

       if (FVB > HFVB)
          FVB = HFVB;

       FVBSO = Math.ceil((FVB + (VBEZBSO * TAB1[J] / 100))*100)/100;

        if (FVBSO > TAB2[J])
           FVBSO = TAB2[J];

       HFVBZSO = (VBEZB + VBEZBSO) /100 - FVBSO;

       FVBZSO = Math.ceil(FVBZ + VBEZBSO/100);

       if(FVBZSO > HFVBZSO)
          FVBZSO = HFVBZSO;

       if (FVBZSO > TAB3[J])
          FVBZSO = TAB3[J];

         HFVBZ = VBEZB / 100 - FVB;

         if(FVBZ > HFVBZ)
           FVBZ = Math.ceil(HFVBZ);

    // MRE4ALTE  Altersentlastungsbetrag

    if (ALTER1 == 0)
       ALTE = 0;
    else {
       if (AJAHR < 2006)
          K = 1;
       else {
          if (AJAHR < 2040)
             K = AJAHR - 2004;
          else
             K = 36;
      }
     }
       BMG = ZRE4J - ZVBEZJ;
       ALTE = Math.ceil(BMG * TAB1[K] * 100) / 100;
       HBALTE = TAB5[K];

       if (ALTE > HBALTE)
          ALTE = HBALTE;
 }

  public void MRE4ABZ() {
   // Ermittlung des Jahresarbeitslohns nach Abzug der Freibeträge, PAP 2009, S. 15
   ZRE4 = ZRE4J - FVB - ALTE - JLFREIB + JLHINZU;
   if(ZRE4 < 0)
     ZRE4 = 0;
   ZRE4VP = ZRE4J - FVB - ALTE;
   if(ZRE4VP < 0)
     ZRE4VP = 0;
   ZVBEZ = ZVBEZJ - FVB;
   if(ZVBEZ < 0)
    ZVBEZ = 0;

   }

  public void MZTABFB() {
  //Ermittlung der festen Tabellenfreibetraege (ohne Vorsorgepauschale) PAP Seite 16

    ANP = 0;
    if (VBEZ > 0) {
       if (ZVBEZ < FVBZ)
          FVBZ = Math.floor(ZVBEZ);   // auf Euro abrunden (nach 2.1 PAP)
    }
    if (STKL < 6) {
       if (ZVBEZ > 0) {
          if (ZVBEZ - FVBZ < 102)
             ANP = Math.floor(ZVBEZ - FVBZ);  // auf Euro abrunden (nach 2.1 PAP)
            else
             ANP = 102;
       }
      }

    else {
     FVBZ = 0;
     FVBZSO = 0;
    }
    if (STKL < 6) {
       if (ZRE4 > ZVBEZ) {
          if (ZRE4 - ZVBEZ < 920)
             ANP = Math.ceil(ANP + ZRE4 - ZVBEZ);
            else
             ANP = ANP + 920;
       }
    }

       KZTAB = 1;
   if (STKL == 1) {
       SAP = 36;
       KFB = ZKF * 6024;
    }
    if (STKL == 2) {
       EFA = 1308;
       SAP = 36;
       KFB = ZKF * 6024;
    }
    if (STKL == 3) {
       KZTAB = 2;
       SAP = 72;
       KFB = ZKF * 6024;
   }
    if (STKL == 4) {
       SAP = 36;
       KFB = ZKF * 3012;
    }
    if (STKL == 5)
       KFB = 0;

    if (STKL == 6)
       KFB = 0;

    ZTABFB = EFA + ANP + SAP + FVBZ;
 }


  public void MLSTJAHR() { //Ermittlung der Jahreslohnsteuer, PAP S. 17

    if (STKL < 5)
       UPEVP();
     else
       VSP = 0;

    if(KENNVMT == 0){
       ZVE = ZRE4 - ZTABFB - VSP;
       UPMLST();
      }
    else {
        ZVE = ZRE4 - ZTABFB - VSP - VMT/100 - VKAPA/100;

      if(ZVE < 0){
       ZVE = (ZVE + VMT/100 + VKAPA/100) / 5;
       UPMLST();
       ST = ST*5;
      }
      else {
       UPMLST();
       STOVMT = ST;
       ZVE = ZVE + (VMT + VKAPA) / 500;
       UPMLST();
       ST = (ST - STOVMT) * 5 + STOVMT;
      }
    }
  }

  public void UPMLST() {

    if (ZVE < 1) {
       ZVE = 0;
       X = 0;
     }
     else
       X = Math.floor(ZVE / KZTAB);  // auf Euro abrunden

     if (STKL < 5)
       uptab09();
     else
       MST5_6();
 }

  public void UPEVP() {
  // Vorsorgepauschale (§39B ABS. 2 SATZ 6 NR 3 ESTG) PAP SEITE 19

    if (KRV > 0)
         VSP1 = 0;
     else {
       if (ZRE4VP > 64800)
            ZRE4VP = 64800;
       VSP1 = 0.36 * ZRE4VP;
       VSP1 = VSP1 * 0.0995;
    }
    VSP2 = 0.11 * ZRE4VP;
    VHB = 1500 * KZTAB;
    if (VSP2 > VHB)
       VSP2 = VHB;
    VSPN = Math.ceil(VSP1 + VSP2);  //auf Euro aufrunden
    MVSP();
    if (VSPN > VSP)
       VSP = VSPN;
}

 public void MVSP() {
 //Vorsorgepauschale (§39B ABS. 2 SATZ 6 NR 3 ESTG) Vergleichsberechnung
 //fuer Guenstigerpruefung PAP Seite 20

    VSPO = ZRE4VP * 0.2;

    VSPVOR = 3068 * KZTAB;
    VSPMAX1 = 1334 * KZTAB;
    VSPMAX2 = 667 * KZTAB;
    VSPKURZ = 1134 * KZTAB;
    if (KRV == 1) {
       if (VSPO > VSPKURZ)
          VSP = VSPKURZ;
        else
          VSP = Math.floor(VSPO);  // auf Euro abrunden
       }
    else
       UMVSP();

 }


  public void UMVSP() {  //Vorsorgepauschale, PAP 2009, S. 21

    VSPVOR = VSPVOR - ZRE4VP * 0.16;

    if (VSPVOR < 0)
       VSPVOR = 0;

    if (VSPO > VSPVOR) {
       VSP = VSPVOR;
       VSPREST = VSPO - VSPVOR;

       if (VSPREST > VSPMAX1) {
          VSP = VSP + VSPMAX1;
          VSPREST = Math.ceil((VSPREST - VSPMAX1)*100) / 200; //auf Cent aufrunden
       if (VSPREST > VSPMAX2)
          VSP = Math.floor(VSP + VSPMAX2); //auf Euro abrunden
       else
          VSP = Math.floor(VSP + VSPREST); //auf Euro abrunden
        }
        else
            VSP = Math.floor(VSP + VSPREST); //auf Euro abrunden
     }
     else
         VSP = Math.floor(VSPO); // auf Euro abrunden
 }

    public void MST5_6() {
    // Lohnsteuer fuer die Steuerklassen V und VI (§ 39B Abs. 2 Satz 8 ESTG) PAP Seite 22

    ZZX = X;
    if (ZZX > 26276) {
       ZX = 26276;
       UP5_6();
       if (ZZX > 200320) {
         ST = ST + (200320 - 26276) * 0.42;
         ST = Math.floor(ST + (ZZX - 200320) * 0.45);
       }
       else
         ST = Math.floor(ST + (ZZX - 26276) * 0.42);
     }
     else {
       ZX = ZZX;
       UP5_6();
       if (ZZX > 9225) {
          VERGL = ST;
          ZX = 9225;
          UP5_6();
          HOCH = Math.floor(ST + (ZZX - 9225) * 0.42);
          if (HOCH < VERGL)
             ST = HOCH;
           else
             ST = VERGL;
        }
     }
  }

  public void UP5_6() {
    X = ZX * 1.25;
    uptab09();
    ST1 = ST;
    X = ZX * 0.75;
    uptab09();
    ST2 = ST;
    DIFF = (ST1 - ST2) * 2;
    MIST = Math.floor(ZX * 0.14);
    if (MIST > DIFF)
       ST = MIST;
     else
       ST = DIFF;
 }

 public void MSOLZ() {   // Solidaritätszuschlag, PAP S. 23
    SOLZFREI = 972 * KZTAB;
    if (JBMG > SOLZFREI) {
       SOLZJ = JBMG * 5.5 / 100;
       SOLZMIN = (JBMG - SOLZFREI) * 20 / 100;
       if (SOLZMIN < SOLZJ)
          SOLZJ = SOLZMIN;
       JW = SOLZJ * 100;
       UPANTEIL();
       SOLZLZZ = ANTEIL1;
     }
     else
       SOLZLZZ = 0;

     if (R > 0){
       JW = JBMG * 100;
       UPANTEIL();
       BK = ANTEIL1;
       }
     else
       BK = 0;
    }


 public void UPANTEIL() {  // Anteil der Jahresbeiträge für einen LZZ
                        // PAP 2009, S. 24
                        // ANTEIL1 abrunden, ANTEIL2 aufrunden
    if (LZZ == 1) {
       ANTEIL1 = JW;
       ANTEIL2 = JW;
    }
    if (LZZ == 2) {
       ANTEIL1 = Math.floor(Math.round(JW * 100 / 12) / 100);
       ANTEIL2 = Math.ceil(JW / 12);
    }
    if (LZZ == 3) {
       ANTEIL1 = Math.floor(Math.round(JW * 700 / 360) / 100);
       ANTEIL2 = Math.ceil(JW * 7 / 360);
    }
    if (LZZ == 4) {
       ANTEIL1 = Math.floor(Math.round(JW * 100 / 360) / 100);
       ANTEIL2 = Math.ceil(JW / 360);
    }
  }

  public void MSONST() {  // Berechnung sonstiger Bezüge, PAP 2009, S. 25

    LZZ = 1;
    if(ZMVB == 0)
      ZMVB = 12;
    if (SONSTB == 0) {
       LSTSO = 0;
       STS = 0;
       SOLZS = 0;
       BKS = 0;
    }
     else {
       MOSONST();
       ZRE4J = (JRE4 + SONSTB) / 100;
       ZVBEZJ = (JVBEZ + VBS) / 100;
       VBEZBSO = STERBE;
       MRE4SONST();
       MLSTJAHR();
       LSTSO = ST * 100;
       STS = LSTSO - LSTOSO;
       if(STS < 0)
         STS=0;
       SOLZS = Math.floor(STS * 5.5 / 100);
       if (R > 0)
          BKS = STS;
        else
          BKS = 0;
    }
   }


public void MVMT() {  // Berechnung der Vergütung für mehrjährige Tätigkeit
                   // PAP 2009, S. 26
    if(VKAPA<0)
       VKAPA=0;
    if (VMT + VKAPA > 0) {

    if(LSTSO == 0) {
         MOSONST();
         LST1 = LSTOSO;
       }
       else
         LST1 = LSTSO;

     VBEZBSO = STERBE + VKAPA;
     ZRE4J = (JRE4 + SONSTB + VMT + VKAPA) / 100;
     ZVBEZJ = (JVBEZ + VBS + VKAPA) / 100;
     MRE4SONST();
     MLSTJAHR();
     LST3 = ST * 100;
     KENNVMT=1;
     MLSTJAHR();
     LST2 = ST * 100;
     STV = LST2 - LST1;
     LST3 = LST3 - LST1;

     LST3 = LST3 - LST1;

       if (LST3 < STV)
          STV = LST3;
       if (STV < 0)
          STV = 0;
       SOLZV = Math.floor(STV * 5.5 / 100);
       if (R > 0)
          BKV = STV;
        else
          BKV = 0;
     }
     else {
       STV = 0;
       SOLZV = 0;
       BKV = 0;
    }
 }

  public void MOSONST() {
    // SONDERBERECHNUNG OHNE SONSTIGE BEZÜGE FÜR BERECHNUNG SONSTIGE BEZÜGE/VERGÜTUNG
    // MEHRJÄHRIGE TÄTIGKEIT. PAP 2009, S. 27

    ZRE4J = JRE4 / 100;
    ZVBEZJ = JVBEZ / 100;
    JLFREIB = JFREIB / 100;
    JLHINZU = JHINZU / 100;
    MRE4();
    MRE4ABZ();
    MZTABFB();
    MLSTJAHR();
    LSTOSO = ST * 100;
  }

  public void MRE4SONST() {
   // Sonderberechnung mit sonstigen Bezüge für Berechnung sonstige Bezüge/Vergütung
    // mehrjährige Tätigkeit. PAP 2009, S. 27

    MRE4();
    FVB = FVBSO;
    MRE4ABZ();
    FVBZ =FVBZSO;
    MZTABFB();

 }

 public void uptab09() {  //tarifliche Einkommensteuer, PAP 2009, S. 28
    if (X < 7835)
          ST = 0;
        else {
        if (X < 13140) {
           Y = (X - 7834) / 10000;
           RW = Y * 939.68;
           RW = RW + 1400;
           ST = Math.floor(RW * Y);
         }
         else {
           if (X < 52552) {
              Y = (X - 13139) / 10000;
              RW = Y * 228.74;
              RW = RW + 2397;
              RW = RW * Y;
              ST = Math.floor(RW + 1007);
            }
         else {
           if(X < 250401)
                ST = Math.floor(X * 0.42 - 8064);
             else
                ST = Math.floor(X * 0.45 - 15576);
              }
           }
       }
    ST = ST * KZTAB;
  }
}

