packages feed

tax-ato 2023.1 → 2023.2

raw patch · 3 files changed

+254/−20 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Tax.ATO: costOfManagingTaxAffairs :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: data Deductions a
+ Data.Tax.ATO: deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: deductionForProjectPool :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: dividendDeductions :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: foreignIncomeDeductions :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: forestryManagedInvestmentSchemeDeduction :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: giftsOrDonations :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: instance GHC.Num.Num a => GHC.Base.Monoid (Data.Tax.ATO.Deductions a)
+ Data.Tax.ATO: instance GHC.Num.Num a => GHC.Base.Semigroup (Data.Tax.ATO.Deductions a)
+ Data.Tax.ATO: interestDeductions :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: lowValuePoolDeduction :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: otherDeductions :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: otherWorkRelatedExpenses :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: paygInstalments :: Lens' (Offsets a) (Money a)
+ Data.Tax.ATO: personalSuperannuationContributions :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: totalDeductions :: (Num a, Ord a) => Deductions a -> Money a
+ Data.Tax.ATO: workRelatedCarExpenses :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: workRelatedClothingLaundryAndDryCleaningExpenses :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: workRelatedSelfEducationExpenses :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: workRelatedTravelExpenses :: Lens' (Deductions a) (Money a)
- Data.Tax.ATO: deductions :: Lens' (TaxReturnInfo y a) (Money a)
+ Data.Tax.ATO: deductions :: Lens' (TaxReturnInfo y a) (Deductions a)

Files

+ CHANGELOG.md view
@@ -0,0 +1,16 @@+## Version 2023.2++- Add support for PAYG Instalments, which are specified in aggregate+  as a refundable tax offset via the `paygInstalments` field.++- Add the `Deductions` type, which expresses the various deduction+  types, as well as the (aggregate) amount of deductions related to+  foreign income.++- Implement the Foreign Income Tax Offset Limit.  The limit will be+  calculated and the `foreignTaxOffset` field in the `TaxReturnInfo`+  will be clamped to it.++## Older versions++See Git commit history
src/Data/Tax/ATO.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE PolyKinds #-}+ -- This file is part of hs-tax-ato -- Copyright (C) 2018-2021  Fraser Tweedale --@@ -96,13 +98,32 @@   , dependentChildren    -- ** Deductions+  , Deductions+  , deductions+  , totalDeductions+  , workRelatedCarExpenses+  , workRelatedTravelExpenses+  , workRelatedClothingLaundryAndDryCleaningExpenses+  , workRelatedSelfEducationExpenses+  , otherWorkRelatedExpenses+  , lowValuePoolDeduction+  , interestDeductions+  , dividendDeductions+  , giftsOrDonations+  , costOfManagingTaxAffairs+  , deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity+  , personalSuperannuationContributions+  , deductionForProjectPool+  , forestryManagedInvestmentSchemeDeduction+  , otherDeductions+  , foreignIncomeDeductions    -- ** Tax offsets-  , deductions   , Offsets   , offsets   , spouseContributionOffset   , foreignTaxOffset+  , paygInstalments    -- ** Assessing tax   , TaxAssessment@@ -128,7 +149,7 @@   , module Data.Tax.ATO.Rounding   ) where -import Control.Lens (Getter, Lens', foldOf, lens, to, view)+import Control.Lens (Getter, Lens', (&), foldOf, lens, set, to, view, views)  import Data.Tax import Data.Tax.ATO.CGT@@ -234,7 +255,7 @@   , _ess :: ESSStatement a   , _foreignIncome :: Money a   , _cgtEvents :: [CGTEvent a]-  , _deductions :: Money a+  , _deductions :: Deductions a   , _offsets :: Offsets a   , _triCapitalLossCarryForward :: Money a   , _phi :: [PrivateHealthInsurancePolicyDetail a]@@ -310,7 +331,7 @@ cgtEvents :: Lens' (TaxReturnInfo y a) [CGTEvent a] cgtEvents = lens _cgtEvents (\s b -> s { _cgtEvents = b }) -deductions :: Lens' (TaxReturnInfo y a) (Money a)+deductions :: Lens' (TaxReturnInfo y a) (Deductions a) deductions = lens _deductions (\s b -> s { _deductions = b })  offsets :: Lens' (TaxReturnInfo y a) (Offsets a)@@ -377,18 +398,24 @@  -- | Consolidated individual tax rate incorporating -- HELP and SFSS repayments--- (if applicable) and automatic offsets (e.g. LITO).+-- (if applicable) and automatic offsets (e.g. LITO, LMITO). individualTax   :: (Fractional a, Ord a)   => TaxTables y a+  -> Tax (Money a) (Money a)+individualTax table =+  greaterOf mempty (ttIndividualIncomeTax table <> ttAdditional table)++-- | Tax to calculate compulsory study and training loan repayments+-- (e.g. HELP, SFSS)+studyAndTrainingLoanRepayment+  :: (Fractional a, Ord a)+  => TaxTables y a   -> TaxReturnInfo y a   -> Tax (Money a) (Money a)-individualTax table info =-    greaterOf mempty $-      ttIndividualIncomeTax table-      <> limit (view helpBalance info) (ttHelp table)-      <> limit (view sfssBalance info) (ttSfss table)-      <> ttAdditional table+studyAndTrainingLoanRepayment table info =+  limit (view helpBalance info) (ttHelp table)+  <> limit (view sfssBalance info) (ttSfss table)  -- | Medicare levy + surcharge medicareLevyTax@@ -422,7 +449,7 @@         , view foreignIncome info         ]     in-      wholeDollars (gross $-$ view deductions info)+      wholeDollars (gross $-$ views deductions totalDeductions info)  instance (Num a) => HasTaxWithheld (TaxReturnInfo y) a a where   taxWithheld = to $ \info ->@@ -438,7 +465,9 @@     cg = assessCGTEvents           (view capitalLossCarryForward info) (view cgtEvents info)     taxable = view income info-    due = getTax (individualTax tables info) taxable+    due = getTax (individualTax tables) taxable+    studyRepayment = getTax (studyAndTrainingLoanRepayment tables info) taxable+    mlAndMLS = getTax (medicareLevyTax tables info) taxable      incomeForSurchargePurposes =       taxable@@ -456,17 +485,34 @@       (ttPHIRebateRates tables)       (view privateHealthInsurancePolicyDetails info) +    foreignIncomeTaxOffsetLimit =+      let+        step1 = due <> mlAndMLS+        step2 =+          let+            info' = info & set foreignIncome mempty+            taxable' = view income info' <> view (deductions . foreignIncomeDeductions) info'+            due' = getTax (individualTax tables) taxable'+            mlAndMLS' = getTax (medicareLevyTax tables info') taxable'+          in+            due' <> mlAndMLS'+        step3 = step1 $-$ step2+      in+        max (Money 1000) step3+     frankingCredit =       wholeDollars       $ foldMap dividendFrankingCredit (view dividends info)     off =       view (offsets . spouseContributionOffset) info-      <> view (offsets . foreignTaxOffset) info+      <> min (view (offsets . foreignTaxOffset) info) foreignIncomeTaxOffsetLimit+      <> view (offsets . paygInstalments) info+   in     TaxAssessment       taxable-      due-      (getTax (medicareLevyTax tables info) taxable)+      (due <> studyRepayment)+      mlAndMLS       (view taxWithheld info)       (frankingCredit <> off)       cg@@ -475,7 +521,7 @@ -- | Australian Business Number type ABN = String --- | PAYG payment summary+-- | PAYG payment summary - individual non-business data PaymentSummary a = PaymentSummary   { summaryABN :: ABN   , summaryGross :: Money a@@ -531,16 +577,28 @@     <> view taxWithheld d  -- | Tax offsets that individuals can claim+--+-- The following lenses are available:+--+-- +---------------------------------------+----------------------------------++-- | 'spouseContributionOffset'            | Spouse super contribution        |+-- +---------------------------------------+----------------------------------++-- | 'foreignTaxOffset'                    | Foreign income tax offset        |+-- +---------------------------------------+----------------------------------++-- | 'paygInstalments'                     | PAYG Instalments                 |+-- +---------------------------------------+----------------------------------++-- data Offsets a = Offsets   { _spouseOffset :: Money a   , _foreignTaxOffset :: Money a+  , _paygInstalments :: Money a   }  instance Num a => Semigroup (Offsets a) where-  Offsets a b <> Offsets a' b' = Offsets (a <> a') (b <> b')+  Offsets a b c <> Offsets a' b' c' = Offsets (a <> a') (b <> b') (c <> c')  instance Num a => Monoid (Offsets a) where-  mempty = Offsets mempty mempty+  mempty = Offsets mempty mempty mempty   mappend = (<>)  -- | Spouse contribution offset.  Maximum of /$540/ (not enforced).@@ -550,6 +608,165 @@ -- | Offset for tax paid on foreign income. foreignTaxOffset :: Lens' (Offsets a) (Money a) foreignTaxOffset = lens _foreignTaxOffset (\s b -> s { _foreignTaxOffset = b })++paygInstalments :: Lens' (Offsets a) (Money a)+paygInstalments = lens _paygInstalments (\s b -> s { _paygInstalments = b })+++-- | Deductions that individuals can claim.+--+-- The only "special case" field is 'foreignIncomeDeductions', which is+-- the aggregate amount of /other/ deductions that pertains to foreign+-- income.  It is used only for calculating the Foreign Income Tax Offset+-- Limit.+--+data Deductions a = Deductions+  { _workRelatedCarExpenses :: Money a+  , _workRelatedTravelExpenses :: Money a+  , _workRelatedClothingLaundryAndDryCleaningExpenses :: Money a+  , _workRelatedSelfEducationExpenses :: Money a+  , _otherWorkRelatedExpenses :: Money a+  , _lowValuePoolDeduction :: Money a+  , _interestDeductions :: Money a+  , _dividendDeductions :: Money a+  , _giftsOrDonations :: Money a+  , _costOfManagingTaxAffairs :: Money a+  , _deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity :: Money a+  , _personalSuperannuationContributions :: Money a+  , _deductionForProjectPool :: Money a+  , _forestryManagedInvestmentSchemeDeduction :: Money a+  , _otherDeductions :: Money a+  , _foreignIncomeDeductions :: Money a+  }++instance Num a => Semigroup (Deductions a) where+  Deductions a b c d e f g h i j k l m n o p+    <> Deductions a' b' c' d' e' f' g' h' i' j' k' l' m' n' o' p'+      = Deductions (a <> a') (b <> b') (c <> c') (d <> d') (e <> e') (f <> f') (g <> g') (h <> h')+                   (i <> i') (j <> j') (k <> k') (l <> l') (m <> m') (n <> n') (o <> o') (p <> p')++instance Num a => Monoid (Deductions a) where+  mempty = Deductions mempty mempty mempty mempty mempty mempty mempty mempty+                      mempty mempty mempty mempty mempty mempty mempty mempty++-- | Sum the deductions.  Negative components are ignored.+totalDeductions :: (Num a, Ord a) => Deductions a -> Money a+totalDeductions a =+  foldMap (max mempty)+    [ view workRelatedCarExpenses a+    , view workRelatedTravelExpenses a+    , view workRelatedClothingLaundryAndDryCleaningExpenses a+    , view workRelatedSelfEducationExpenses a+    , view otherWorkRelatedExpenses a+    , view lowValuePoolDeduction a+    , view interestDeductions a+    , view dividendDeductions a+    , view giftsOrDonations a+    , view costOfManagingTaxAffairs a+    , view deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity a+    , view personalSuperannuationContributions a+    , view deductionForProjectPool a+    , view forestryManagedInvestmentSchemeDeduction a+    , view otherDeductions a+    ]++-- | __D1__ Work-related car expenses+workRelatedCarExpenses :: Lens' (Deductions a) (Money a)+workRelatedCarExpenses =+  lens _workRelatedCarExpenses (\s b -> s { _workRelatedCarExpenses = b })++-- | __D2__ Work-related travel expenses+workRelatedTravelExpenses :: Lens' (Deductions a) (Money a)+workRelatedTravelExpenses =+  lens _workRelatedTravelExpenses (\s b -> s { _workRelatedTravelExpenses = b })++-- | __D3__ Work-related clothing, laundry and dry-cleaning expenses+workRelatedClothingLaundryAndDryCleaningExpenses :: Lens' (Deductions a) (Money a)+workRelatedClothingLaundryAndDryCleaningExpenses =+  lens+    _workRelatedClothingLaundryAndDryCleaningExpenses+    (\s b -> s { _workRelatedClothingLaundryAndDryCleaningExpenses = b })++-- | __D4__ Work-related self-education expenses+workRelatedSelfEducationExpenses :: Lens' (Deductions a) (Money a)+workRelatedSelfEducationExpenses =+  lens _workRelatedSelfEducationExpenses (\s b -> s { _workRelatedSelfEducationExpenses = b })++-- | __D5__ Other work-related expenses+otherWorkRelatedExpenses :: Lens' (Deductions a) (Money a)+otherWorkRelatedExpenses =+  lens _otherWorkRelatedExpenses (\s b -> s { _otherWorkRelatedExpenses = b })++-- | __D6__ Low-value pool deduction+lowValuePoolDeduction :: Lens' (Deductions a) (Money a)+lowValuePoolDeduction =+  lens _lowValuePoolDeduction (\s b -> s { _lowValuePoolDeduction = b })++-- | __D7__ Interest deductions+interestDeductions :: Lens' (Deductions a) (Money a)+interestDeductions =+  lens _interestDeductions (\s b -> s { _interestDeductions = b })++-- | __D8__ Dividend deductions+dividendDeductions :: Lens' (Deductions a) (Money a)+dividendDeductions =+  lens _dividendDeductions (\s b -> s { _dividendDeductions = b })++-- | __D9__ Gifts or donations+giftsOrDonations :: Lens' (Deductions a) (Money a)+giftsOrDonations =+  lens _giftsOrDonations (\s b -> s { _giftsOrDonations = b })++-- | __D10__ Cost of managing tax affairs+costOfManagingTaxAffairs :: Lens' (Deductions a) (Money a)+costOfManagingTaxAffairs =+  lens _costOfManagingTaxAffairs (\s b -> s { _costOfManagingTaxAffairs = b })++-- | __D11__ Deductible amount of undeducted purchase price of a foreign pension or annuity+deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity :: Lens' (Deductions a) (Money a)+deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity =+  lens+    _deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity +    (\s b -> s { _deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity = b })++-- | __D12__ Personal superannuation contributions+personalSuperannuationContributions :: Lens' (Deductions a) (Money a)+personalSuperannuationContributions =+  lens _personalSuperannuationContributions (\s b -> s { _personalSuperannuationContributions = b })++-- | __D13__ Deduction for project pool+deductionForProjectPool :: Lens' (Deductions a) (Money a)+deductionForProjectPool =+  lens _deductionForProjectPool (\s b -> s { _deductionForProjectPool = b })++-- | __D14__ Forestry managed investment scheme deduction+forestryManagedInvestmentSchemeDeduction :: Lens' (Deductions a) (Money a)+forestryManagedInvestmentSchemeDeduction =+  lens+    _forestryManagedInvestmentSchemeDeduction+    (\s b -> s { _forestryManagedInvestmentSchemeDeduction = b })++-- | __D15__ Other deductions — not claimable at __D1__ to __D14__ or elsewhere+-- in your tax return+otherDeductions :: Lens' (Deductions a) (Money a)+otherDeductions =+  lens _otherDeductions (\s b -> s { _otherDeductions = b })++-- | Aggregate of deductions related to foreign income, including:+--+-- * Deductions that are reasonably related to amounts on which foreign+--   income tax has been paid+-- * Debt deductions attributable to your overseas permanent establishment+-- * Amount of the foreign loss component of one or more tax losses deducted+--   in the income year.+--+-- The components making up this amount __must be included in other fields__.+-- This field is only used in calculating the Foreign Income Tax Offset Limit.+--+foreignIncomeDeductions :: Lens' (Deductions a) (Money a)+foreignIncomeDeductions =+  lens _foreignIncomeDeductions (\s b -> s { _foreignIncomeDeductions = b })+  -- | A gross income (first argument) and amount of tax withheld (second argument) data GrossAndWithheld a = GrossAndWithheld (Money a) (Money a)
tax-ato.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.2 name:                tax-ato-version:             2023.1+version:             2023.2 synopsis:            Tax types and computations for Australia description:   This library provides types and tax computations for tax@@ -16,6 +16,7 @@ build-type:          Simple tested-with:         GHC ==8.10.7 || ==9.0.2 || ==9.2.7 || ==9.4.4 || ==9.6.1 extra-source-files:+  CHANGELOG.md   .hlint.yaml  homepage:            https://github.com/frasertweedale/hs-tax-ato