canadian-income-tax-2024.0.0.1: src/Tax/Canada/Province/ON/ON428/Fix.hs
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Tax.Canada.Province.ON.ON428.Fix (ON428, fixON428) where
import Data.Fixed (Centi)
import Rank2 qualified
import Tax.Canada.Province.ON.ON428.Types
import Tax.Canada.Shared (fixBaseCredit, fixMedicalExpenses, fixSubCalculation, fixTaxIncomeBracket,
BaseCredit(cont), MedicalExpenses (difference),
SubCalculation (result), TaxIncomeBracket (equalsTax))
import Tax.Util (fixEq, fractionOf, nonNegativeDifference, totalOf)
import Prelude hiding (floor, ceiling)
fixON428 :: ON428 Maybe -> ON428 Maybe
fixON428 = fixEq $ \on428@ON428{..}-> ON428{page1 = fixPage1 page1,
page2 = fixPage2 on428 page2,
page3 = fixPage3 on428 page3,
page4 = fixPage4 on428 page4}
fixPage1 :: Page1 Maybe -> Page1 Maybe
fixPage1 = fixEq $ \Page1{..}-> Page1{
line1 = line1,
partA = fixPage1PartA line1 partA,
partB = fixPage1PartB partB}
fixPage1PartA :: Maybe Centi -> Page1PartA Maybe -> Page1PartA Maybe
fixPage1PartA income = fixEq $ \Page1PartA{..}-> Page1PartA{
column1 = fixTaxIncomeBracket income (Just column2) column1,
column2 = fixTaxIncomeBracket income (Just column3) column2,
column3 = fixTaxIncomeBracket income (Just column4) column3,
column4 = fixTaxIncomeBracket income (Just column5) column4,
column5 = fixTaxIncomeBracket income Nothing column5}
fixPage1PartB :: Page1PartB Maybe -> Page1PartB Maybe
fixPage1PartB = fixEq $ \part@Page1PartB{..}-> part{
line9_basic = Just 12_399,
spouseAmount = fixBaseCredit spouseAmount,
dependantAmount = fixBaseCredit dependantAmount,
line18 = totalOf [line9_basic, line10_age, spouseAmount.cont, dependantAmount.cont, line17_caregiver],
line24_sum = fixSubCalculation id $
totalOf [line19_cppQpp,
line20_cppQpp,
line21_employmentInsurance,
line22_employmentInsurance,
line23_adoption],
line25 = totalOf [line18, line24_sum.result]}
fixPage2 :: ON428 Maybe -> Page2 Maybe -> Page2 Maybe
fixPage2 on428 = fixEq $ \Page2{..}-> Page2{
partB = fixPage2PartB on428 partB,
partC = fixPage2PartC on428 partC}
fixPage2PartB :: ON428 Maybe -> Page2PartB Maybe -> Page2PartB Maybe
fixPage2PartB on428 = fixEq $ \part@Page2PartB{..}-> part{
line26 = on428.page1.partB.line25,
line28 = totalOf [line26, line27_pension],
line31 = totalOf [line28, line29_disability, line30],
line35 = totalOf [line31, line32_interest, line33_education, line34_transferred],
medicalExpenses = fixMedicalExpenses 2806 medicalExpenses,
line43_sum = fixSubCalculation id $ totalOf [medicalExpenses.difference, line42],
line44 = totalOf [line35, line43_sum.result],
line46_fraction = line45_rate `fractionOf` line44,
donations = fixDonations donations,
line50 = totalOf [line46_fraction, donations.line49_sum.result]}
fixPage2PartC :: ON428 Maybe -> Page2PartC Maybe -> Page2PartC Maybe
fixPage2PartC on428 = fixEq $ \part@Page2PartC{..}-> part{
line51_tax = totalOf [on428.page1.partA.column1.equalsTax,
on428.page1.partA.column2.equalsTax,
on428.page1.partA.column3.equalsTax,
on428.page1.partA.column4.equalsTax,
on428.page1.partA.column5.equalsTax],
line52_credits = on428.page2.partB.line50,
line53 = nonNegativeDifference line51_tax line52_credits,
line55 = totalOf [line53, line54],
line56 = line53,
line58 = nonNegativeDifference line56 line57,
line59_product = Just 0.3367 `fractionOf` line59_copy,
line60_lesser = min <$> line58 <*> line59_product,
line61 = nonNegativeDifference line55 line60_lesser}
fixDonations :: Donations Maybe -> Donations Maybe
fixDonations = fixEq $ \part@Donations{..} -> part{
line47_fraction = Just 0.0505 `fractionOf` line47_base,
line48_fraction = Just 0.1116 `fractionOf` line48_base,
line49_sum = fixSubCalculation id $ totalOf [line47_fraction, line48_fraction]}
fixPage3 :: ON428 Maybe -> Page3 Maybe -> Page3 Maybe
fixPage3 on428 = fixEq $ \page@Page3{..}-> page{
line62 = on428.page2.partC.line61,
line63 = line62,
line64 = on428.page2.partC.line54,
line65 = nonNegativeDifference line63 line64,
line66_surtax = fixSubCalculation (\x-> 0.2 * max 0 (x - 5554)) line65,
line67_surtax = fixSubCalculation (\x-> 0.36 * max 0 (x - 7108)) line65,
line68_sum = fixSubCalculation id $ totalOf [line66_surtax.result, line67_surtax.result],
line69 = totalOf [line62, line68_sum.result],
line70 = on428.page2.partC.line57,
line71 = nonNegativeDifference line69 line70,
line73 = totalOf [line71, line72],
line75_amount = ((506 *) . fromIntegral) <$> line75_childrenNum,
line76_amount = ((506 *) . fromIntegral) <$> line76_childrenNum,
line77 = totalOf [line74_basicReduction, line75_amount, line76_amount],
line78_double = fixSubCalculation (2 *) line77,
line79 = line73,
line80_difference = fixSubCalculation id $ nonNegativeDifference line78_double.result line79,
line81 = nonNegativeDifference line73 line80_difference.result,
line83 = nonNegativeDifference line81 line82}
fixPage4 :: ON428 Maybe -> Page4 Maybe -> Page4 Maybe
fixPage4 on428 = fixEq $ \page@Page4{..}-> page{
line84 = on428.page3.line83,
line86 = nonNegativeDifference line84 line85_lift,
line87_fraction = Just 0.25 `fractionOf` line87_foodDonations,
line88 = nonNegativeDifference line86 line87_fraction,
line89_health = totalOf [between 0 20000 0,
healthPremium.row1.equalsTax,
between 25000 36000 300,
healthPremium.row2.equalsTax,
between 38500 48000 450,
healthPremium.row3.equalsTax,
between 48600 72000 600,
healthPremium.row4.equalsTax,
between 72600 200000 750,
healthPremium.row5.equalsTax,
if income > 200600 then Just 900 else Nothing],
line90 = totalOf [line88, line89_health],
healthPremium = fixHealthPremium income healthPremium}
where income = sum on428.page1.line1
between floor ceiling tax
| income > floor && income <= ceiling = Just tax
| otherwise = Nothing
fixHealthPremium :: Centi -> HealthPremium Maybe -> HealthPremium Maybe
fixHealthPremium income = fixEq $ \HealthPremium{..}-> HealthPremium{
row1 = fixHealthPremiumBracket income 20000 25000 0.06 0 row1,
row2 = fixHealthPremiumBracket income 36000 38500 0.06 300 row2,
row3 = fixHealthPremiumBracket income 48000 48600 0.25 450 row3,
row4 = fixHealthPremiumBracket income 72000 72600 0.25 600 row4,
row5 = fixHealthPremiumBracket income 200000 200600 0.25 750 row5}
fixHealthPremiumBracket :: Centi -> Centi -> Centi -> Rational -> Centi
-> HealthPremiumBracket Maybe -> HealthPremiumBracket Maybe
fixHealthPremiumBracket income floor ceiling rate base HealthPremiumBracket{..}
| income > floor && income < ceiling = HealthPremiumBracket{
taxableIncome = Just income,
overThreshold = Just $ income - floor,
timesRate = Just rate `fractionOf` overThreshold,
equalsTax = totalOf [timesRate, Just base]}
| otherwise = Rank2.pure Nothing