packages feed

canadian-income-tax-2022.2: src/Tax/Canada/T1/Fix.hs

{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

module Tax.Canada.T1.Fix (fixT1) where

import Control.Applicative ((<|>))
import Data.Fixed (Centi)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import Data.Time.Calendar (Year, dayPeriod)
import Rank2 qualified

import Tax.Canada.T1.Types
import Tax.Util (difference, fixEq, leastOf, nonNegativeDifference, totalOf)

fixT1 :: T1 Maybe -> T1 Maybe
fixT1 = fixEq $ \t1@T1{..}-> T1{page1 = fixPage1 page1,
                                page2 = fixPage2 page2,
                                page3 = fixPage3 page3,
                                page4 = fixPage4 t1 page4,
                                page5 = fixPage5 t1 page5,
                                page6 = fixPage6 t1 page6,
                                page7 = fixPage7 t1 page7,
                                page8 = fixPage8 t1 page8}

fixPage1 :: Page1 Maybe -> Page1 Maybe
fixPage1 = id

fixPage2 :: Page2 Maybe -> Page2 Maybe
fixPage2 = id

fixPage3 :: Page3 Maybe -> Page3 Maybe
fixPage3 = fixEq $ \page@Page3{..}-> page{
   line_19 = totalOf [line_10100_EmploymentIncome ,
                      line_10400_OtherEmploymentIncome,
                      line_11300_OldAgeSecurityPension,
                      line_11400_CPP_QPP,
                      line_11500_OtherPensions,
                      line_11600_ElectedSplitPension,
                      line_11700_UCCB,
                      line_11900_EmploymentInsurance,
                      line_12000_TaxableDividends,
                      line_12100_InvestmentIncome,
                      line_12200_PartnershipIncome,
                      line_12500_RDSP,
                      line_12600_Amount,
                      line_12700_TaxableCapitalGains,
                      line_12800_Amount,
                      line_12900_RRSPIncome,
                      line_13000_OtherIncome,
                      line_13010_Taxablescholarship],
   line_25_sum = totalOf [line_13500_Amount,
                          line_13700_Amount,
                          line_13900_Amount,
                          line_14100_Amount,
                          line_14300_Amount],
   line_25_cont = line_25_sum,
   line_26 = totalOf [line_19, line_25_cont],
   line_14700_EqualsAmount = totalOf [line_14400_WorkersCompBen,
                                      line_14500_SocialAssistPay,
                                      line_14600_NetFedSupplements],
   line_14700_PlusAmount = line_14700_EqualsAmount,
   line_15000_TotalIncome = totalOf [line_26, line_14700_PlusAmount]}

fixPage4 :: T1 Maybe -> Page4 Maybe -> Page4 Maybe
fixPage4 t1 = fixEq $ \page@Page4{..}-> page{
   line_15000_TotalIncome_2 = t1.page3.line_15000_TotalIncome,
   line_23300_sum = totalOf [line_20700_RPPDeduction,
                             line_20800_RRSPDeduction,
                             line_21000_SplitPensionDeduction,
                             line_21200_Dues,
                             line_21300_UCCBRepayment,
                             line_21400_ChildCareExpenses,
                             line_21500_DisabilityDeduction,
                             line_21700_Amount,
                             line_21900_MovingExpenses,
                             line_22000_Amount,
                             line_22100_CarryingChargesInterest,
                             line_22200_CPP_QPP_Contributions,
                             line_22215_DeductionCPP_QPP,
                             line_22400_XplorationDevExpenses,
                             line_22900_OtherEmployExpenses,
                             line_23100_ClergyResDeduction,
                             line_23200_OtherDeductions,
                             line_23210],
   line_23300_cont = line_23300_sum,
   line_23400_NetBeforeAdjust = nonNegativeDifference line_15000_TotalIncome_2 line_23300_cont,
   line_23600_NetIncome = nonNegativeDifference line_23400_NetBeforeAdjust line_23500_SocialBenefits}

fixPage5 :: T1 Maybe -> Page5 Maybe -> Page5 Maybe
fixPage5 t1 = fixEq $ \Page5{..}-> Page5{
   step4_TaxableIncome = fixStep4 t1 step4_TaxableIncome,
   partA_FederalTax = fixPage5PartA t1 partA_FederalTax,
   partB_FederalTaxCredits = fixPage5PartB t1 partB_FederalTaxCredits}

fixPage6 :: T1 Maybe -> Page6 Maybe -> Page6 Maybe
fixPage6 t1 = fixEq $ \page@Page6{..}-> page{
   line82 = t1.page5.partB_FederalTaxCredits.line_81,
   line31260 = leastOf [Just 1287,
                        totalOf [t1.page3.line_10100_EmploymentIncome, t1.page3.line_10400_OtherEmploymentIncome]],
   line94_sum = totalOf [line30800,
                         line31000,
                         line31200,
                         line31217,
                         line31220,
                         line31240,
                         line31260,
                         line31270,
                         line31285,
                         line31300,
                         line31350],
   line94_cont = line94_sum,
   line96 = totalOf [line82, line94_cont, line31400],
   line99 = totalOf [line96, line31600, line31800],
   line104 = totalOf [line99, line31900, line32300, line32400, line32600],
   medical_expenses = fixMedicalExpenses t1 medical_expenses,
   line33200_sum = totalOf [medical_expenses.difference, medical_expenses.otherDependants],
   line33200_cont = line33200_sum,
   line33500 = totalOf [line104, line33200_cont],
   line33800 = (* 0.15) <$> line33500,
   line35000 = totalOf [line33800, line34900]}

fixPage7 :: T1 Maybe -> Page7 Maybe -> Page7 Maybe
fixPage7 t1 = fixEq $ \Page7{partC_NetFederalTax, step6_RefundOrBalanceOwing}-> Page7{
   partC_NetFederalTax = fixPage7PartC t1 partC_NetFederalTax,
   step6_RefundOrBalanceOwing = fixPage7Step6 t1 step6_RefundOrBalanceOwing}

fixPage8 :: T1 Maybe -> Page8 Maybe -> Page8 Maybe
fixPage8 t1 = fixEq $ \page@Page8{..}-> Page8{
   step6_RefundOrBalanceOwing = fixPage8Step6 t1 step6_RefundOrBalanceOwing,
   line48400_Refund = step6_RefundOrBalanceOwing.line164_Refund_or_BalanceOwing
                      >>= \x-> if x < 0 then Just (negate x) else Nothing,
   line48500_BalanceOwing = step6_RefundOrBalanceOwing.line164_Refund_or_BalanceOwing
                            >>= \x-> if x > 0 then Just x else Nothing,
   line_46600 = (-) <$> line48400_Refund <*> line_46500,
   ..}

fixStep4 :: T1 Maybe -> Step4 Maybe -> Step4 Maybe
fixStep4 t1 = fixEq $ \step@Step4{..}-> step{
   line_23600_NetIncome_2 = t1.page4.line_23600_NetIncome,
   line_25700_AddLines_sum = totalOf [line_24400_MilitaryPoliceDeduction,
                                      line_24900_SecurityDeductions,
                                      line_25000_OtherPayDeductions,
                                      line_25100_PartnershipLosses,
                                      line_25200_NoncapitalLosses,
                                      line_25300_NetCapitalLosses,
                                      line_25400_CapitalGainsDeduction,
                                      line_25500_NorthernDeductions,
                                      line_25600_AdditionalDeductions_Amount],
   line_25700_AddLines_cont = line_25700_AddLines_sum,
   line_26000_TaxableIncome = nonNegativeDifference line_23600_NetIncome_2 line_25700_AddLines_cont}

fixPage5PartA :: T1 Maybe -> Page5PartA Maybe -> Page5PartA Maybe
fixPage5PartA t1 = fixEq $ \part@Page5PartA{..}-> part{
   column1 = taxIncomeBracket 0 50197 0.15 0,
   column2 = taxIncomeBracket 50197 100392 0.205 7529.55,
   column3 = taxIncomeBracket 100392 155625 0.26 17819.53,
   column4 = taxIncomeBracket 155625 221708 0.29 32180.11,
   column5 = taxIncomeBracket 221708 (10^12) 0.33 51344.18} -- a trillion ought to be enough for anybody
   where taxIncomeBracket threshold ceiling rate baseTax
            | income > threshold && income <= ceiling = TaxIncomeBracket{
                 line67_income = Just income,
                 line69_overThreshold = Just (income - threshold),
                 line71_timesRate = Just ((income - threshold) * rate),
                 line73_equalsTax = Just ((income - threshold) * rate + baseTax)}
            | otherwise = Rank2.pure Nothing
         income = fromMaybe 0 t1.page5.step4_TaxableIncome.line_26000_TaxableIncome

fixPage5PartB :: T1 Maybe -> Page5PartB Maybe -> Page5PartB Maybe
fixPage5PartB t1 = fixEq $ \part@Page5PartB{..}-> part{
   line30000 = let income = fromMaybe 0 t1.page4.line_23600_NetIncome
               in if income <= 155625 then Just 14398
                  else if income >= 221708 then Just 12719
                       else Just $ 14398 - (14398 - 12719) * (income - 155625) / (221708 - 155625),
   line30100 = if any ((<= (1957 :: Year)) . dayPeriod) t1.page1.identification.dateBirth
               then Just 12719
               else Nothing,
   line30500 =  ((* 2350) . fromIntegral) <$> line30499_ChildrenNum,
   line_81 = totalOf [line30000,
                      line30100,
                      line30300,
                      line30400,
                      line30425,
                      line30450,
                      line30500]}

fixMedicalExpenses :: T1 Maybe -> MedicalExpenses Maybe -> MedicalExpenses Maybe
fixMedicalExpenses t1 = fixEq $ \expenses@MedicalExpenses{familyExpenses, taxableIncome,
                                                          taxableIncomeFraction, threshold}-> expenses{
   taxableIncome = t1.page4.line_23600_NetIncome,
   taxableIncomeFraction = (* 0.03) <$> taxableIncome,
   threshold = min 2479 <$> taxableIncomeFraction,
   difference = nonNegativeDifference familyExpenses threshold}

fixPage7PartC :: T1 Maybe -> Page7PartC Maybe -> Page7PartC Maybe
fixPage7PartC t1 = fixEq $ \part@Page7PartC{..}-> part{
   line116 = let partA = t1.page5.partA_FederalTax
             in partA.column1.line73_equalsTax
                <|> partA.column2.line73_equalsTax
                <|> partA.column3.line73_equalsTax
                <|> partA.column4.line73_equalsTax
                <|> partA.column5.line73_equalsTax,
   line40400 = totalOf [line116, line40424],
   line119 = t1.page6.line35000,
   line40425,
   line40427,
   line122_sum = totalOf [line119, line40425, line40427],
   line122_cont = line122_sum,
   line123 = nonNegativeDifference line40400 line122_cont,
   line125 = totalOf [line123, line124],
   line127 = difference line125 line40500,
   line129 = totalOf [line127, line128],
   line131 = nonNegativeDifference line129 line130,
   line41000 = case line40900
               of Just x
                    | x <= 400 -> Just (x * 0.75)
                    | x <= 750 -> Just ((x - 400) * 0.5 + 300)
                    | otherwise-> Just ((x - 750) * 0.3333 + 475)
                  Nothing -> Nothing,
   line41600_sum = totalOf [line41000, line41200, line41400],
   line41600_cont = line41600_sum,
   line41700 = nonNegativeDifference line131 line41600_cont,
   line42000 = totalOf [line41700, line41500, line41800]}

fixPage7Step6 :: T1 Maybe -> Page7Step6 Maybe -> Page7Step6 Maybe
fixPage7Step6 t1 = fixEq $ \step@Page7Step6{..}-> step{
   line140 = t1.page7.partC_NetFederalTax.line42000,
   line_43500_TotalPayable = totalOf [line140, line_42100_CPPContributions, line_42120_EIPremiums,
                                      line_42200_SocialBenefits, line_42800_ProvTerrTax]}

fixPage8Step6 :: T1 Maybe -> Page8Step6 Maybe -> Page8Step6 Maybe
fixPage8Step6 t1 = fixEq $ \step@Page8Step6{..}-> step{
   line_43500_totalpayable = t1.page7.step6_RefundOrBalanceOwing.line_43500_TotalPayable,
   line_46900 = (* 0.25) <$> line_46800,
   line_48200_sum = totalOf [line_43700_Total_income_tax_ded,
                             line_44000,
                             line_44800_CPPOverpayment,
                             line_45000_EIOverpayment,
                             line_45200_MedicalExpense,
                             line_45300_CWB,
                             line_45350_CTC,
                             line_45400_InvestmentTaxCredit,
                             line_45600_TrustTaxCredit,
                             line_45700_GST_HST_Rebate,
                             line_46900,
                             line_47555_TaxPaid,
                             line_47556,
                             line_47557,
                             line_47600_TaxPaid,
                             line_47900_ProvTerrCredits],
   line_48200_cont = line_48200_sum,
   line164_Refund_or_BalanceOwing = difference line_43500_totalpayable line_48200_sum}