{-# LANGUAGE NoMonomorphismRestriction , OverloadedStrings #-} -- | -- TODO: (lohnsteuern) werbungskosten -- -- Beachten: Lebensversicherungen -- https://www.smartsteuer.de/portal/lexikon/L/Lebensversicherung.html#D063053300009 -- -- http://www.finanzen-versicherungen-blog.de/besteuerung-lebensversicherung-auszahlung-lebensversicherung-steuerfreie-lebensversicherung/ -- module HAX.Germany.Einkommensteuer where import HAX.Accounting import HAX.Bookkeeping import Control.Monad.Writer import qualified Data.Map as M import HAX.Common import HAX.Germany.Subjekte import HAX.Germany.Gewerbe -- * Konten -- ** Vermögen privatVermoegen = "Verm" -- ** Aufwandskonten ertragsKonten = [ erstattungsUeberhaenge , privateVerausserungsgeschaefte , einkuenfteAusBeteiligungenAnKapitalgesellschaftenKapEst , einkuenfteAusBeteiligungenAnKapitalgesellschaften , sonstigeEinkuenfteAusKapitalvermoegenKapEst , sonstigeEinkuenfteAusKapitalvermoegen , ausserordentlicheEinkuenfte , arbeitslohn , steuerfreieEinnahmen , uebrigeSummeDerEinkuenfte , einkuenfteAusGewerbebetrieb ] einkuenfteAusGewerbebetrieb = "EGW" steuerfreieEinnahmen = "StFrei" -- | positive oder negative summe aller Einkunftsarten außer aus -- Kapitalvermögen und privaten Veräußerungsgeschäften uebrigeSummeDerEinkuenfte = "SdE" arbeitslohn = "Lohn" werbungskostensNichtSelbststaendigeArbeitOhneFahrten = "WerbNSA" ausserordentlicheEinkuenfte = "ausserE" -- ^ gesetz. Renten, Pensionen, Bezüge, .. -- im Sinne des https://www.jurion.de/Gesetze/EStG/24a -- -- https://www.smartsteuer.de/portal/lexikon/A/Altersentlastungsbetrag.html einkuenfteAusBeteiligungenAnKapitalgesellschaftenKapEst = "EBKK" -- ^ nicht solche, die der tariflichen/persönlichen ESt. unterliegen (z.B. aus -- Betriebsvermögen) einkuenfteAusBeteiligungenAnKapitalgesellschaften = "EBK" -- ^ beachten: 40% steuerfrei (?) sonstigeEinkuenfteAusKapitalvermoegenKapEst = "EKVE" -- ^ nicht solche, die der tariflichen/persönlichen ESt. unterliegen sonstigeEinkuenfteAusKapitalvermoegen = "EKV" -- ^ einkuenfteAusKapitalvermoegen'hen nach 32d Abs 2. -- http://www2.nwb.de/portal/content/ir/service/news/news_1413444.aspx -- http://www.haufe.de/finance/finance-office-professional/rechtmaessigkeit-der-tariflichen-besteuerung-nach-32d-abs-2-nr-1b-estg_idesk_PI11525_HI5088406.html -- -- https://www.smartsteuer.de/portal/lexikon/E/Einkuenfte-aus-Kapitalvermoegen.html privateVerausserungsgeschaefte = "PV" erstattungsUeberhaenge = "eUeb" -- * Aufwandskonten aufwandsKonten = [ sonstigeVorsorgeAufwendungOhneBasisbeitraege , krankenundPflegeversicherungBasisbeitraege , privatAusgaben , altersvorsorgeAufwendungenArbeitgeberAnteil , altersvorsorgeAufwendungenEigenanteil , werbungskostensNichtSelbststaendigeArbeitOhneFahrten , lohnSteuer ] lohnSteuer = "LSt" altersvorsorgeAufwendungenEigenanteil = "AvAE" -- ^ gesetzliche Renten / Rürüp riesterRentenEinzahlung :: IsString a => a riesterRentenEinzahlung = error "riesterRente not implemented" -- ^ not implemented! -- -- riester rente (+ zulagen. aber nur bis 2100 €??. von -- Steuerersparnis durch SA wird die Zulage abgezogen. Aber nur wenn -- ergebnis positiv) altersvorsorgeAufwendungenArbeitgeberAnteil = "AvAA" krankenundPflegeversicherungBasisbeitraege = "KPB" -- ^ Kranken- und Pflegeversicherung Basisbeitraege" -- -- nur 96% der Leistungen wenn Krankengeld enthalten sonstigeVorsorgeAufwendungOhneBasisbeitraege = "sVA" privatAusgaben = "PA" -- * Types type AccNat l w = Acc NatuerlichePerson l w type Betrag l w = Acc NatuerlichePerson l w Amount type AccNatRW = AccountingRW NatuerlichePerson type BetragRW = AccountingRW NatuerlichePerson Amount type AccNatRO = AccountingReadOnly NatuerlichePerson type BetragRO = AccountingReadOnly NatuerlichePerson Amount -- * Utility kinderGeld :: NatuerlichePerson -> Amount kinderGeld p = g $ kinderMitKindergeld p where g 1 = 184 g 2 = g 1 + 184 g 3 = g 2 + 190 g n = g (n-1) + 215 -- | Calcuate the current age in years alter :: Monoid w => AccNat l w Int alter = do geb <- readBody pGeburt date <- reader eDate return $ yearSpan $ dateSpan geb date -- | Calcuate in which year reaches a certain age jahrInDemManSoAltWird :: Monoid w => Int -> AccNat l w Int jahrInDemManSoAltWird x = readBody $ getYear . shift (months $ 12 * x) . pGeburt splitFaktor p = if pSplitting p then 2 else 1 -- * Berechnung -- | Calculates of the Einkommensteuer for all possible variants, -- selects the cheapest (Günstigervergleich) and applies it -- (e.g. Verlust Vortäge). einkommenSteuer :: GewerbeSteuer -> BetragRW einkommenSteuer gewst = fixed $ pass $ do name <- reader eName moeglichkeiten <- forM (range (minBound,maxBound)) -- [V False False () ()] $ \v -> (,) v <$> listen (einkommenSteuerVariante gewst v + abgeltungsSteuer v) let (variante,(steuer,action)) = minimumBy (comparing $ fst.snd) moeglichkeiten (soli,actionSoli) <- listen $ solidaritaetsZuschlag gewst variante let actualAction = do logLedger $ printf "Die Günstigerprüfung ergibt: %v\n" $ show variante logLedger $ printf "Ersparnisse gegenüber anderen Varianten: %v\n" $ show $ (roundTo 0.(steuer-).fst.snd) <$> moeglichkeiten action actionSoli return (steuer, const actualAction) -- * Günstigervergleich -- | Type representing the different possible variants of -- Einkommensteuer calculation to be compared data Variante = V { mitKinderFreibetrag :: Bool , teileinkuenfteVerfahren :: Bool -- ^ wahlrecht nach § 32d Abs. 2 Nr. 3 EStG -- https://www.smartsteuer.de/portal/lexikon/A/Aktien.html -- https://www.smartsteuer.de/portal/lexikon/A/Abgeltungsteuer.html#D063109700011 -- ^ http://de.wikipedia.org/wiki/Teileink%C3%BCnfteverfahren -- -- https://www.smartsteuer.de/portal/lexikon/E/Einkuenfte-aus-Kapitalvermoegen.html#D063026000028 -- -- damit ist nicht gemeint 32d Abs 6 -- https://www.smartsteuer.de/portal/lexikon/A/Abgeltungsteuer.html#D063109700006 -- http://www.steuernetz.de/aav_steuernetz/lexikon/K-36317.xhtml?currentModule=home -- -- sondern 32 Abs. 2 Nr. 3 EStG , riesterRente :: () -- ^ not implemented , vorsorgeaufwendungenAlteRegel :: () -- ^ not implemented } deriving (Bounded,Eq,Ord,Ix,Show) type VarBetragRO = Variante -> BetragRO type VarBetrag l w = Variante -> Betrag l w -- * Berechnung der Einkünfte -- firmenWagenNutzung :: -- | https://www.smartsteuer.de/portal/lexikon/E/Einkuenfte-aus-Kapitalvermoegen.html#D063026000031 -- -- http://de.wikipedia.org/wiki/Sparer-Pauschbetrag -- einkuenfteAusKapitalvermoegen' = withBody $ \p -> -- assert (>=0) (positivePart $ -- haben einkuenfteAusKapitalvermoegen - (splitFaktor p * 801)) -- "Verlust aus Kapitalvermoegen not implemented" -- ^ https://www.smartsteuer.de/portal/lexikon/E/Einkuenfte-aus-nichtselbststaendiger-Arbeit.html -- -- https://www.smartsteuer.de/portal/lexikon/E/Entfernungspauschale.html -- -- https://www.smartsteuer.de/portal/lexikon/W/Werbungskostenpauschbetrag.html einkuefteAusNichtSelbststaendigerArbeit' = do einkuenfte <- haben arbeitslohn entfernungsPauschale' <- readBody $ entfernungsPauschale . pWagen sonstige <- soll werbungskostensNichtSelbststaendigeArbeitOhneFahrten let werbungskosten = max (entfernungsPauschale' + sonstige) $ min (positivePart einkuenfte) 1000 -- pauschbetrag nur bis zur Höhe der Einküfte singleLog "Enternungspauschale: %v\n" entfernungsPauschale' singleLog "Werbungskosten (nicht-selbstständige Arbeit): %v\n" werbungskosten singleLog "Einkuefte Aus nicht-selbstständiger Arbeit: %v\n" einkuenfte return $ einkuenfte - werbungskosten summeDerEinkuenfte :: VarBetragRO summeDerEinkuenfte v = singleResult "Summe der Einkuenfte" $ uebrigeSummeDerEinkuenfte' v + einkuefteAusNichtSelbststaendigerArbeit' + haben ausserordentlicheEinkuenfte -- http://www.gesetze-im-internet.de/estg/__3c.html -- 3 Nr. 40 EStG uebrigeSummeDerEinkuenfte' :: VarBetragRO uebrigeSummeDerEinkuenfte' v = singleResult "Summe der übrigen Einkuenfte" $ haben uebrigeSummeDerEinkuenfte + haben sonstigeEinkuenfteAusKapitalvermoegen + haben einkuenfteAusBeteiligungenAnKapitalgesellschaften + 0.6 * when' (teileinkuenfteVerfahren v) (haben einkuenfteAusBeteiligungenAnKapitalgesellschaftenKapEst) -- * Steuerberechnung -- | Calculates the Einkommensteuer for a given variant einkommenSteuerVariante :: GewerbeSteuer -> VarBetragRO einkommenSteuerVariante gewst v = do zvE <- zuVersteuerndesEinkommen v tariflicheEinkommensteuer <- return $ steuerBetrag zvE geminderteTariflicheEinkommensteuer <- return tariflicheEinkommensteuer -- - Minderungsbetrag nach Punkt 11 Ziffer 2 des Schlussprotokolls zu Art. 23 DBA Belgien -- - ausländische Steuer nach § 34c Abs. 1 und 6 EStG, § 12 AStG festzusetzendeEinkommensteuer <- return geminderteTariflicheEinkommensteuer - gewStErmaessigung gewst tariflicheEinkommensteuer + kinderGeldAnrechnung v tell $ logLedger $ printf "festzusetzende Einkommensteuer: %v\n" festzusetzendeEinkommensteuer return $ festzusetzendeEinkommensteuer -- | https://www.smartsteuer.de/portal/lexikon/S/Solidaritaetszuschlag.html -- -- TODO eigentlich unter berücksichtigung von Kinderfreibeträgen? -- -- https://www.jurion.de/Gesetze/SolZG/3 -- -- http://www.steuerlinks.de/steuerlexikon/lexikon/gewerbesteueranrechnung.html solidaritaetsZuschlag :: GewerbeSteuer -- ^ GewerbeSteuer -> VarBetragRO solidaritaetsZuschlag gewst v = singleResult "Solidaritätszuschlag" $ withBody $ \p -> do let soliVariante = v{mitKinderFreibetrag=True} fEst <- singleResult "Bemessungsgrundlage für Solidaritätszuschlag" $ mute $ einkommenSteuerVariante gewst soliVariante - kinderGeldAnrechnung soliVariante let zuschlag1 = fEst * solidaritaetsFaktor zuschlag2 = 0.2 * positivePart (fEst - (splitFaktor p * 972)) return $ min zuschlag1 zuschlag2 -- | https://www.smartsteuer.de/portal/lexikon/S/Steuerermaessigung-bei-Einkuenften-aus-Gewerbebetrieb.html -- -- 35 EStG -- -- http://books.google.de/books?id=NY1oFSCGGM0C&pg=PA123&lpg=PA123&dq=35+estg+verlustausgleich&source=bl&ots=hXL1TzqbyG&sig=cky8FRnixRZVTOMzWWRh7X8A_6Q&hl=en&sa=X&ei=eHUDVODgGcbqaPXMgcAK&ved=0CEoQ6AEwBA#v=onepage&q=35%20estg%20verlustausgleich&f=false gewStErmaessigung :: GewerbeSteuer -> Amount -- ^ geminderte Einkommensteuer -> BetragRO gewStErmaessigung gewst est = singleResult "Gewerbesteuerermäßigung" $ do einkGew <- positivePart $ haben einkuenfteAusGewerbebetrieb when' (einkGew > 0) $ do positiveEinkunfte <- sum <$> mapM (positivePart.haben) ertragsKonten let hoechstBetrag = einkGew / positiveEinkunfte * est return $ max hoechstBetrag $ max (gwSteuer gewst) $ gwMessbetrag gewst * 3.8 -- | Berechnet den Tariflichen Einkommensteuerbetrag für das zu -- versteuernde Einkommen steuerBetrag :: Amount -> Amount steuerBetrag zvE | zvE <= ks !! 0 = 0 | zvE <= ks !! 1 = (97458/100*y+1400)*y | zvE <= ks !! 2 = (22874/100*z+2397)*z+971 | zvE <= ks !! 3 = 42/100*(zvE-ks !! 2)+13971 | True = 45/100*(zvE-ks !! 3)+97067 where y = (zvE-ks !! 0)/10000 z = (zvE-ks !! 1)/10000 ks = [8354,13469,52881,250730]; testSteuerBetrag = all (\(x,y) -> y == steuerBetrag x) [(4000,0.0) ,(12000,639.9939990728) ,(24000,3748.9578455914) ,(48000,11975.5534967914) ,(120000,42160.98)] -- | https://www.smartsteuer.de/portal/lexikon/A/Abgeltungsteuer.html abgeltungsSteuer :: VarBetragRO abgeltungsSteuer v = withBody $ \p -> do 0.25 * positivePart (haben sonstigeEinkuenfteAusKapitalvermoegenKapEst + when' (not $ teileinkuenfteVerfahren v) (haben einkuenfteAusBeteiligungenAnKapitalgesellschaftenKapEst) - (splitFaktor p * 801)) -- | Calculate the "zu versteuerndes Einkommen" for a given variant -- https://www.smartsteuer.de/portal/lexikon/E/Einkommensteuer.html -- -- more references in the source code... zuVersteuerndesEinkommen :: VarBetragRO zuVersteuerndesEinkommen v = do sdE <- summeDerEinkuenfte v -- https://www.smartsteuer.de/portal/lexikon/G/Gesamtbetrag-der-Einkuenfte.html gesamtbetragderEinkuenfte <- return sdE -- https://www.smartsteuer.de/portal/lexikon/P/Private-Veraeusserungsgeschaefte.html#D063064400040 + assert (>= 0) (haben privateVerausserungsgeschaefte) "Verlust aus privaten Verausserungsgeschaeften not implemented" - altersentlastungsBetrag v - entlastungsbetragfuerAlleinerziehende tell $ logLedger $ printf "Gesamtbetrag der Einkünfte: %s" gesamtbetragderEinkuenfte einkommen <- return gesamtbetragderEinkuenfte -- https://www.smartsteuer.de/portal/lexikon/G/Gesamtbetrag-der-Einkuenfte.html -- https://www.smartsteuer.de/portal/lexikon/S/Sonderausgaben.html#D063071200006 + haben erstattungsUeberhaenge -- vorzutragender verlust nur bei negativen SdE (§ 10d Abs.1 EStG ) - verlustAbzug "ESt" (if sdE < 0 then sdE else positivePart gesamtbetragderEinkuenfte) - sonderAusgaben - aussergewoehnlicheBelastungen -- - sonderAfA -- + zuzurechnendes Einkommen gem. § 15 Abs. 1 AStG zvE <- return einkommen -- https://www.smartsteuer.de/portal/lexikon/K/Kinderfreibetrag.html - kinderFreibetrag v -- - Härteausgleich tell $ logLedger $ printf "zu versteuerndes Einkommen: %v" zvE return zvE mute = censor (const mempty) -- * Sonderausgaben und Belastungen aussergewoehnlicheBelastungen = ausbildungsKosten -- § 10 EStG (3) -- http://de.wikipedia.org/wiki/Sonderausgabe_(Steuerrecht) -- https://www.smartsteuer.de/portal/lexikon/S/Sonderausgaben.html sonderAusgaben :: BetragRO sonderAusgaben = allgemeineSonderAusgaben + altersvorsorgeAufwendungen + sonstigeVorsorgeAufwendung -- | allgemeine Sonderausgaben (z.B. auch die -- Kirchensteuer beinhalten) -- -- Aktuel nur Pauschbetrag implementiert allgemeineSonderAusgaben :: BetragRO allgemeineSonderAusgaben = singleResult "allg. Sonderaushaben" $ readBody $ \p -> 36 * splitFaktor p -- | http://www.ruv.de/de/r_v_ratgeber/altersvorsorge/foerderung_staat/5_basisrente_sonderausgabenabzug.jsp -- -- http://www.steuernetz.de/aav_steuernetz/lexikon/K-23995.xhtml?currentModule=home altersvorsorgeAufwendungen :: BetragRO altersvorsorgeAufwendungen = singleResult "Altersvorsorgeaufwendungen" $ withBody $ \p -> do eigenanteil <- soll altersvorsorgeAufwendungenEigenanteil arbeitgeber <- soll altersvorsorgeAufwendungenArbeitgeberAnteil jahr <- reader $ fromIntegral . getYear . eDate let satz = min 1 $ 0.76 + (jahr - 2013) * 0.02 return $ satz * (min (splitFaktor p * 20000) $ eigenanteil + arbeitgeber) - arbeitgeber -- | http://www.steuernetz.de/aav_steuernetz/lexikon/K-24101.xhtml?currentModule=home -- -- TODO bis 2019 möglicher Günsitgervergleich mit Berechnungsmethode bis 2004? sonstigeVorsorgeAufwendung :: BetragRO sonstigeVorsorgeAufwendung = singleResult "sonstige Vorsorgeaufwendungen" $ withBody f where f p = do basis <- soll krankenundPflegeversicherungBasisbeitraege sonstige <- soll sonstigeVorsorgeAufwendungOhneBasisbeitraege return $ max basis -- mindestens die Basisbeiträge $ min (hbSelbst + hbPartner) -- höchstens die Höchstebeträge $ basis + sonstige where hoechstBetrag ohneZus = if ohneZus then 2800 else 1900 hbSelbst = hoechstBetrag $ krankenUndPflegeOhneZuschuesse p hbPartner = when' (pSplitting p) $ hoechstBetrag $ fromMaybe (error $ "krankenUndPflegeOhneZuschuessePartner is nothing") $ krankenUndPflegeOhneZuschuessePartner p -- * Sonstiges entlastungsbetragfuerAlleinerziehende :: BetragRO entlastungsbetragfuerAlleinerziehende = withBody $ \p -> do singleResult "Entlastungsbetrag für Alleinerziehende" $ when' (kinderMitKindergeldImHaushalt p && not (pSplitting p)) 1308 kinderFreibetrag :: VarBetragRO kinderFreibetrag v = singleResult "Kinderfreibetrag" $ when' (mitKinderFreibetrag v) (fst <$> kinderFreibetragUndGeld) kinderGeldAnrechnung :: VarBetragRO kinderGeldAnrechnung v = singleResult "Kindergeld Anrechnung" $ when' (mitKinderFreibetrag v) (snd <$> kinderFreibetragUndGeld) ausbildungsKosten :: BetragRO ausbildungsKosten = singleResult "Ausbildungskosten" $ readBody $ \p -> splitFaktor p * 924/2 * pAuswaertigeKinderInBerufsausbildung p -- | Berechnet den anzurechnenden Freibetrag und das abzuziehende Kindergeld kinderFreibetragUndGeld :: Monoid w => Acc NatuerlichePerson l w (Amount, Amount) kinderFreibetragUndGeld = withBody $ \p -> do let faktor = if pSplitting p || kinderFreibetragsVerdopplung p then 1 else 0.5 return (faktor * kinderMitKindergeld p * 7008, 12 * faktor * kinderGeld p) -- | -- -- altersentlastungsBetrag :: VarBetragRO altersentlastungsBetrag v = withBody $ \p -> do grundlage <- haben arbeitslohn + positivePart (mute $ uebrigeSummeDerEinkuenfte' v) when (pSplitting p) $ error "altersentlastungsBetrag für Splitting not implemented" -- Im Fall der Zusammenveranlagung von Ehegatten ist die Anwendung -- des Altersentlastungsbetrages für jeden Ehegatten gesondert zu -- prüfen (H 24a [Altersentlastungsbetrag bei Ehegatten] EStH). (prozent, hoechst) <- eigenerAltersentlastungsSatz <$> jahrInDemManSoAltWird 65 singleResult "Altersentlastungsbetrag" $ return $ min hoechst $ grundlage * prozent where eigenerAltersentlastungsSatz jahr = if jahr > 2014 then (0,0) else altersentlastungsSaetze ! jahr altersentlastungsSaetze :: Array Int (Amount,Amount) altersentlastungsSaetze = assocArray [( 2005,( 40.0, 1900 )) ,( 2006,( 38.4, 1824 )) ,( 2007,( 36.8, 1748 )) ,( 2008,( 35.2, 1672 )) ,( 2009,( 33.6, 1596 )) ,( 2010,( 32.0, 1520 )) ,( 2011,( 30.4, 1444 )) ,( 2012,( 28.8, 1368 )) ,( 2013,( 27.2, 1292 )) ,( 2014,( 25.6, 1216 )) ,( 2015,( 24.0, 1140 )) ,( 2016,( 22.4, 1064 )) ,( 2017,( 20.8, 988 )) ,( 2018,( 19.2, 912 )) ,( 2019,( 17.6, 836 )) ,( 2020,( 16.0, 760 )) ,( 2021,( 15.2, 722 )) ,( 2022,( 14.4, 684 )) ,( 2023,( 13.6, 646 )) ,( 2024,( 12.8, 608 )) ,( 2025,( 12.0, 570 )) ,( 2026,( 11.2, 532 )) ,( 2027,( 10.4, 494 )) ,( 2028,( 9.6, 456 )) ,( 2029,( 8.8, 418 )) ,( 2030,( 8.0, 380 )) ,( 2031,( 7.2, 342 )) ,( 2032,( 6.4, 304 )) ,( 2033,( 5.6, 266 )) ,( 2034,( 4.8, 228 )) ,( 2035,( 4.0, 190 )) ,( 2036,( 3.2, 152 )) ,( 2037,( 2.4, 114 )) ,( 2038,( 1.6, 76 )) ,( 2039,( 0.8, 38 )) ,( 2040,( 0.0, 0 )) ]