{-# LANGUAGE PolyKinds #-}

-- This file is part of hs-tax-ato
-- Copyright (C) 2018-2021  Fraser Tweedale
--
-- hs-tax-ato is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Affero General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU Affero General Public License for more details.
--
-- You should have received a copy of the GNU Affero General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.

{-|

Types and computations for taxes in Australia.

No guarantee that computations are correct, complete or current.

Lots of things are not implemented, including (but not limited to):
__ETPs__, income from __partnerships and trusts__,
__superannuation__ income streams and lump payments, tax losses from
previous years, __Medicare levy reduction/exemption__, adjustments,
and variations based on family income and dependents.

-}

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}

module Data.Tax.ATO
  (
  -- * Individual tax returns
    TaxReturnInfo
  , newTaxReturnInfo
  , newTaxReturnInfoForTables
  , income

  -- ** Income

  -- *** PAYG Payment Summaries
  , PaymentSummary(..)
  , paymentSummaries
  , ABN

  -- *** Interest
  , interest

  -- *** Dividends and franking credits
  , Dividend(..)
  , dividends
  , dividendFrankingCredit

  -- *** Capital gains tax (CGT)
  , HasCapitalLossCarryForward(..)
  , cgtEvents

  -- *** Employee share schemes
  , ESSStatement
  , newESSStatement
  , ess
  , essTaxedUpfrontReduction
  , essTaxedUpfrontNoReduction
  , essDeferral
  , essPre2009
  , essTFNAmounts
  , essForeignSourceDiscounts

  -- *** Foreign income
  , foreignIncome

  -- ** Medicare Levy Surcharge and Private Health Insurance
  , mlsExemption
  , privateHealthInsurancePolicyDetails

  -- ** Student loan balances
  , helpBalance
  , sfssBalance

  -- ** Spouse details
  , SpouseDetails
  , spouseDetails
  , newSpouseDetails
  , spouseTaxableIncome

  -- ** Income Tests
  , IncomeTests
  , incomeTests
  , newIncomeTests
  , taxFreeGovernmentPensionsOrBenefits
  , targetForeignIncome
  , childSupportPaid
  , dependentChildren

  -- ** Deductions
  , Deductions
  , deductions
  , totalDeductions
  , workRelatedCarExpenses
  , workRelatedTravelExpenses
  , workRelatedClothingLaundryAndDryCleaningExpenses
  , workRelatedSelfEducationExpenses
  , otherWorkRelatedExpenses
  , lowValuePoolDeduction
  , interestDeductions
  , dividendDeductions
  , giftsOrDonations
  , costOfManagingTaxAffairs
  , deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity
  , personalSuperannuationContributions
  , deductionForProjectPool
  , forestryManagedInvestmentSchemeDeduction
  , otherDeductions
  , foreignIncomeDeductions

  -- ** Tax offsets
  , Offsets
  , offsets
  , spouseContributionOffset
  , foreignTaxOffset
  , paygInstalments

  -- ** Assessing tax
  , TaxAssessment
  , assessTax
  , taxBalance
  , taxDue
  , medicareLevyDue
  , taxCreditsAndOffsets
  , taxCGTAssessment
  , privateHealthInsuranceRebateAdjustment

  -- * Corporate tax
  , corporateTax

  -- * Miscellaneous
  , GrossAndWithheld(..)
  , HasTaxWithheld(..)
  , Proportion
  , getProportion
  , proportion
  , module Data.Tax
  , module Data.Tax.ATO.PrivateHealthInsuranceRebate
  , module Data.Tax.ATO.Rounding
  ) where

import Control.Lens (Getter, Lens', (&), foldOf, lens, set, to, view, views)

import Data.Tax
import Data.Tax.ATO.CGT
import Data.Tax.ATO.Common
import Data.Tax.ATO.Days
import Data.Tax.ATO.PrivateHealthInsuranceRebate
import Data.Tax.ATO.Rounding

-- | Data that can have an amount of tax withheld
class HasTaxWithheld a b c where
  taxWithheld :: Getter (a b) (Money c)

instance (Foldable t, HasTaxWithheld x a a, Num a)
            => HasTaxWithheld t (x a) a where
  taxWithheld :: Getter (t (x a)) (Money a)
taxWithheld = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to (forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall {k} (a :: k -> *) (b :: k) c.
HasTaxWithheld a b c =>
Getter (a b) (Money c)
taxWithheld))

-- TODO part year spouse
newtype SpouseDetails a = SpouseDetails
  { forall a. SpouseDetails a -> Money a
_spouseTaxableIncome :: Money a
  -- TODO other fields
  }

newSpouseDetails :: (Num a) => SpouseDetails a
newSpouseDetails :: forall a. Num a => SpouseDetails a
newSpouseDetails = forall a. Money a -> SpouseDetails a
SpouseDetails forall a. Monoid a => a
mempty

spouseTaxableIncome :: Lens' (SpouseDetails a) (Money a)
spouseTaxableIncome :: forall a. Lens' (SpouseDetails a) (Money a)
spouseTaxableIncome =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. SpouseDetails a -> Money a
_spouseTaxableIncome (\SpouseDetails a
s Money a
b -> SpouseDetails a
s { _spouseTaxableIncome :: Money a
_spouseTaxableIncome = Money a
b })

data IncomeTests a = IncomeTests
  { forall a. IncomeTests a -> Money a
_govBenefit :: Money a
  , forall a. IncomeTests a -> Money a
_targetForeignIncome :: Money a
  , forall a. IncomeTests a -> Money a
_childSupportPaid :: Money a
  , forall a. IncomeTests a -> Integer
_dependents :: Integer
  }

newIncomeTests :: (Num a) => IncomeTests a
newIncomeTests :: forall a. Num a => IncomeTests a
newIncomeTests = forall a. Money a -> Money a -> Money a -> Integer -> IncomeTests a
IncomeTests forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty Integer
0

taxFreeGovernmentPensionsOrBenefits :: Lens' (IncomeTests a) (Money a)
taxFreeGovernmentPensionsOrBenefits :: forall a. Lens' (IncomeTests a) (Money a)
taxFreeGovernmentPensionsOrBenefits =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. IncomeTests a -> Money a
_govBenefit (\IncomeTests a
s Money a
b -> IncomeTests a
s { _govBenefit :: Money a
_govBenefit = Money a
b })

targetForeignIncome :: Lens' (IncomeTests a) (Money a)
targetForeignIncome :: forall a. Lens' (IncomeTests a) (Money a)
targetForeignIncome =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. IncomeTests a -> Money a
_targetForeignIncome (\IncomeTests a
s Money a
b -> IncomeTests a
s { _targetForeignIncome :: Money a
_targetForeignIncome = Money a
b })

childSupportPaid :: Lens' (IncomeTests a) (Money a)
childSupportPaid :: forall a. Lens' (IncomeTests a) (Money a)
childSupportPaid =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. IncomeTests a -> Money a
_childSupportPaid (\IncomeTests a
s Money a
b -> IncomeTests a
s { _childSupportPaid :: Money a
_childSupportPaid = Money a
b })

dependentChildren :: Lens' (IncomeTests a) Integer
dependentChildren :: forall a. Lens' (IncomeTests a) Integer
dependentChildren =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. IncomeTests a -> Integer
_dependents (\IncomeTests a
s Integer
b -> IncomeTests a
s { _dependents :: Integer
_dependents = Integer
b })


-- | Individual tax return information.
--
-- Use 'newTaxReturnInfo' to construct.  Alternatively,
-- 'newTaxReturnInfoForTables' can be used to coerce the type
-- parameters to be the same as some 'TaxTables'.
--
-- The following lenses are available:
--
-- +---------------------------------------+----------------------------------+
-- | 'mlsExemption'                        | Medicare levy exemption          |
-- +---------------------------------------+----------------------------------+
-- | 'helpBalance'                         | HELP account balance             |
-- +---------------------------------------+----------------------------------+
-- | 'sfssBalance'                         | SFSS account balance             |
-- +---------------------------------------+----------------------------------+
-- | 'paymentSummaries'                    | PAYG payment summaries           |
-- +---------------------------------------+----------------------------------+
-- | 'interest'                            | Interest data                    |
-- +---------------------------------------+----------------------------------+
-- | 'dividends'                           | Dividend data                    |
-- +---------------------------------------+----------------------------------+
-- | 'ess'                                 | Employee Share Scheme statement  |
-- +---------------------------------------+----------------------------------+
-- | 'foreignIncome'                       | Foreign income                   |
-- +---------------------------------------+----------------------------------+
-- | 'cgtEvents'                           | Capital gains and losses         |
-- +---------------------------------------+----------------------------------+
-- | 'deductions'                          | Deductions                       |
-- +---------------------------------------+----------------------------------+
-- | 'offsets'                             | Tax offsets                      |
-- +---------------------------------------+----------------------------------+
-- | 'privateHealthInsurancePolicyDetails' | Private health insurance         |
-- |                                       | policy details                   |
-- +---------------------------------------+----------------------------------+
-- | 'spouseDetails'                       | Spouse Details (or @Nothing@)    |
-- +---------------------------------------+----------------------------------+
-- | 'incomeTests'                         | Income Tests                     |
-- +---------------------------------------+----------------------------------+
--
data TaxReturnInfo y a = TaxReturnInfo
  { forall (y :: Year) a. TaxReturnInfo y a -> Days y
_mlsExemption :: Days y
  , forall (y :: Year) a. TaxReturnInfo y a -> Money a
_helpBalance :: Money a
  , forall (y :: Year) a. TaxReturnInfo y a -> Money a
_sfssBalance :: Money a
  , forall (y :: Year) a. TaxReturnInfo y a -> [PaymentSummary a]
_paymentSummaries :: [PaymentSummary a]
  , forall (y :: Year) a. TaxReturnInfo y a -> GrossAndWithheld a
_interest :: GrossAndWithheld a
  , forall (y :: Year) a. TaxReturnInfo y a -> [Dividend a]
_dividends :: [Dividend a]
  , forall (y :: Year) a. TaxReturnInfo y a -> ESSStatement a
_ess :: ESSStatement a
  , forall (y :: Year) a. TaxReturnInfo y a -> Money a
_foreignIncome :: Money a
  , forall (y :: Year) a. TaxReturnInfo y a -> [CGTEvent a]
_cgtEvents :: [CGTEvent a]
  , forall (y :: Year) a. TaxReturnInfo y a -> Deductions a
_deductions :: Deductions a
  , forall (y :: Year) a. TaxReturnInfo y a -> Offsets a
_offsets :: Offsets a
  , forall (y :: Year) a. TaxReturnInfo y a -> Money a
_triCapitalLossCarryForward :: Money a
  , forall (y :: Year) a.
TaxReturnInfo y a -> [PrivateHealthInsurancePolicyDetail a]
_phi :: [PrivateHealthInsurancePolicyDetail a]
  , forall (y :: Year) a. TaxReturnInfo y a -> Maybe (SpouseDetails a)
_spouseDetails :: Maybe (SpouseDetails a)
  , forall (y :: Year) a. TaxReturnInfo y a -> IncomeTests a
_incomeTests :: IncomeTests a
  }

-- | Construct a new 'TaxReturnInfo'.
--
-- All monetary fields and lists are initially empty.
--
-- The /Medicare levy surcharge exemption/ field is initially
-- set to the number of days in the year (i.e. the taxpayer is
-- fully exempt).
--
newTaxReturnInfo
  :: (DaysInYear y, Num a)
  => TaxReturnInfo y a
newTaxReturnInfo :: forall (y :: Year) a. (DaysInYear y, Num a) => TaxReturnInfo y a
newTaxReturnInfo = forall (y :: Year) a.
Days y
-> Money a
-> Money a
-> [PaymentSummary a]
-> GrossAndWithheld a
-> [Dividend a]
-> ESSStatement a
-> Money a
-> [CGTEvent a]
-> Deductions a
-> Offsets a
-> Money a
-> [PrivateHealthInsurancePolicyDetail a]
-> Maybe (SpouseDetails a)
-> IncomeTests a
-> TaxReturnInfo y a
TaxReturnInfo
  forall (a :: Year). DaysInYear a => Days a
daysAll  -- MLS exemption
  forall a. Monoid a => a
mempty -- HELP
  forall a. Monoid a => a
mempty -- SFSS
  forall a. Monoid a => a
mempty -- payment summaries
  forall a. Monoid a => a
mempty -- interest
  forall a. Monoid a => a
mempty -- dividends
  forall a. Monoid a => a
mempty -- ESS
  forall a. Monoid a => a
mempty -- foreign income
  forall a. Monoid a => a
mempty -- CGT events
  forall a. Monoid a => a
mempty -- deductions
  forall a. Monoid a => a
mempty -- offsets
  forall a. Monoid a => a
mempty -- cap loss carry forward
  forall a. Monoid a => a
mempty -- private health insurance policy details
  forall a. Maybe a
Nothing -- spouse details
  forall a. Num a => IncomeTests a
newIncomeTests

-- | Construct a 'TaxReturnInfo' per 'newTaxReturnInfo',
-- coercing the type parameters to match the 'TaxTables'
-- argument (which is ignored).
--
newTaxReturnInfoForTables
  :: (DaysInYear y, Num a)
  => TaxTables y a -> TaxReturnInfo y a
newTaxReturnInfoForTables :: forall (y :: Year) a.
(DaysInYear y, Num a) =>
TaxTables y a -> TaxReturnInfo y a
newTaxReturnInfoForTables TaxTables y a
_ = forall (y :: Year) a. (DaysInYear y, Num a) => TaxReturnInfo y a
newTaxReturnInfo

instance HasCapitalLossCarryForward (TaxReturnInfo y) a where
  capitalLossCarryForward :: Lens' (TaxReturnInfo y a) (Money a)
capitalLossCarryForward = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> Money a
_triCapitalLossCarryForward
      (\TaxReturnInfo y a
s Money a
b -> TaxReturnInfo y a
s { _triCapitalLossCarryForward :: Money a
_triCapitalLossCarryForward = Money a
b })

helpBalance :: Lens' (TaxReturnInfo y a) (Money a)
helpBalance :: forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Money a)
helpBalance = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> Money a
_helpBalance (\TaxReturnInfo y a
s Money a
b -> TaxReturnInfo y a
s { _helpBalance :: Money a
_helpBalance = Money a
b })

sfssBalance :: Lens' (TaxReturnInfo y a) (Money a)
sfssBalance :: forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Money a)
sfssBalance = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> Money a
_sfssBalance (\TaxReturnInfo y a
s Money a
b -> TaxReturnInfo y a
s { _sfssBalance :: Money a
_sfssBalance = Money a
b })

mlsExemption :: Lens' (TaxReturnInfo y a) (Days y)
mlsExemption :: forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Days y)
mlsExemption = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> Days y
_mlsExemption (\TaxReturnInfo y a
s Days y
b -> TaxReturnInfo y a
s { _mlsExemption :: Days y
_mlsExemption = Days y
b })

paymentSummaries :: Lens' (TaxReturnInfo y a) [PaymentSummary a]
paymentSummaries :: forall (y :: Year) a. Lens' (TaxReturnInfo y a) [PaymentSummary a]
paymentSummaries = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> [PaymentSummary a]
_paymentSummaries (\TaxReturnInfo y a
s [PaymentSummary a]
b -> TaxReturnInfo y a
s { _paymentSummaries :: [PaymentSummary a]
_paymentSummaries = [PaymentSummary a]
b })

interest :: Lens' (TaxReturnInfo y a) (GrossAndWithheld a)
interest :: forall (y :: Year) a.
Lens' (TaxReturnInfo y a) (GrossAndWithheld a)
interest = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> GrossAndWithheld a
_interest (\TaxReturnInfo y a
s GrossAndWithheld a
b -> TaxReturnInfo y a
s { _interest :: GrossAndWithheld a
_interest = GrossAndWithheld a
b })

dividends :: Lens' (TaxReturnInfo y a) [Dividend a]
dividends :: forall (y :: Year) a. Lens' (TaxReturnInfo y a) [Dividend a]
dividends = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> [Dividend a]
_dividends (\TaxReturnInfo y a
s [Dividend a]
b -> TaxReturnInfo y a
s { _dividends :: [Dividend a]
_dividends = [Dividend a]
b })

ess :: Lens' (TaxReturnInfo y a) (ESSStatement a)
ess :: forall (y :: Year) a. Lens' (TaxReturnInfo y a) (ESSStatement a)
ess = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> ESSStatement a
_ess (\TaxReturnInfo y a
s ESSStatement a
b -> TaxReturnInfo y a
s { _ess :: ESSStatement a
_ess = ESSStatement a
b })

foreignIncome :: Lens' (TaxReturnInfo y a) (Money a)
foreignIncome :: forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Money a)
foreignIncome = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> Money a
_foreignIncome (\TaxReturnInfo y a
s Money a
b -> TaxReturnInfo y a
s { _foreignIncome :: Money a
_foreignIncome = Money a
b })

cgtEvents :: Lens' (TaxReturnInfo y a) [CGTEvent a]
cgtEvents :: forall (y :: Year) a. Lens' (TaxReturnInfo y a) [CGTEvent a]
cgtEvents = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> [CGTEvent a]
_cgtEvents (\TaxReturnInfo y a
s [CGTEvent a]
b -> TaxReturnInfo y a
s { _cgtEvents :: [CGTEvent a]
_cgtEvents = [CGTEvent a]
b })

deductions :: Lens' (TaxReturnInfo y a) (Deductions a)
deductions :: forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Deductions a)
deductions = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> Deductions a
_deductions (\TaxReturnInfo y a
s Deductions a
b -> TaxReturnInfo y a
s { _deductions :: Deductions a
_deductions = Deductions a
b })

offsets :: Lens' (TaxReturnInfo y a) (Offsets a)
offsets :: forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Offsets a)
offsets = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> Offsets a
_offsets (\TaxReturnInfo y a
s Offsets a
b -> TaxReturnInfo y a
s { _offsets :: Offsets a
_offsets = Offsets a
b })

privateHealthInsurancePolicyDetails
  :: Lens' (TaxReturnInfo y a) [PrivateHealthInsurancePolicyDetail a]
privateHealthInsurancePolicyDetails :: forall (y :: Year) a.
Lens' (TaxReturnInfo y a) [PrivateHealthInsurancePolicyDetail a]
privateHealthInsurancePolicyDetails = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a.
TaxReturnInfo y a -> [PrivateHealthInsurancePolicyDetail a]
_phi (\TaxReturnInfo y a
s [PrivateHealthInsurancePolicyDetail a]
b -> TaxReturnInfo y a
s { _phi :: [PrivateHealthInsurancePolicyDetail a]
_phi = [PrivateHealthInsurancePolicyDetail a]
b })

spouseDetails :: Lens' (TaxReturnInfo y a) (Maybe (SpouseDetails a))
spouseDetails :: forall (y :: Year) a.
Lens' (TaxReturnInfo y a) (Maybe (SpouseDetails a))
spouseDetails = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> Maybe (SpouseDetails a)
_spouseDetails (\TaxReturnInfo y a
s Maybe (SpouseDetails a)
b -> TaxReturnInfo y a
s { _spouseDetails :: Maybe (SpouseDetails a)
_spouseDetails = Maybe (SpouseDetails a)
b })

incomeTests :: Lens' (TaxReturnInfo y a) (IncomeTests a)
incomeTests :: forall (y :: Year) a. Lens' (TaxReturnInfo y a) (IncomeTests a)
incomeTests = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall (y :: Year) a. TaxReturnInfo y a -> IncomeTests a
_incomeTests (\TaxReturnInfo y a
s IncomeTests a
b -> TaxReturnInfo y a
s { _incomeTests :: IncomeTests a
_incomeTests = IncomeTests a
b })


-- | A tax assessment.  Use 'assessTax' to compute a
-- @TaxAssessment@.
data TaxAssessment a = TaxAssessment
  { forall a. TaxAssessment a -> Money a
_taxableIncome :: Money a
  , forall a. TaxAssessment a -> Money a
_taxDue :: Money a
  , forall a. TaxAssessment a -> Money a
_medicareLevyDue :: Money a
  , forall a. TaxAssessment a -> Money a
_taxWithheld :: Money a
  , forall a. TaxAssessment a -> Money a
_taxCreditsAndOffsets :: Money a
  , forall a. TaxAssessment a -> CGTAssessment a
_taCGTAssessment :: CGTAssessment a
  , forall a. TaxAssessment a -> Money a
_phiAdj :: Money a
  }

-- | Taxable income
instance HasIncome TaxAssessment a a where
  income :: Getter (TaxAssessment a) (Money a)
income = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a. TaxAssessment a -> Money a
_taxableIncome

instance HasTaxWithheld TaxAssessment a a where
  taxWithheld :: Getter (TaxAssessment a) (Money a)
taxWithheld = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a. TaxAssessment a -> Money a
_taxWithheld

taxDue :: Getter (TaxAssessment a) (Money a)
taxDue :: forall a. Getter (TaxAssessment a) (Money a)
taxDue = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a. TaxAssessment a -> Money a
_taxDue

medicareLevyDue :: Getter (TaxAssessment a) (Money a)
medicareLevyDue :: forall a. Getter (TaxAssessment a) (Money a)
medicareLevyDue = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a. TaxAssessment a -> Money a
_medicareLevyDue

taxCreditsAndOffsets :: Getter (TaxAssessment a) (Money a)
taxCreditsAndOffsets :: forall a. Getter (TaxAssessment a) (Money a)
taxCreditsAndOffsets = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a. TaxAssessment a -> Money a
_taxCreditsAndOffsets

taxCGTAssessment :: Lens' (TaxAssessment a) (CGTAssessment a)
taxCGTAssessment :: forall a. Lens' (TaxAssessment a) (CGTAssessment a)
taxCGTAssessment = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. TaxAssessment a -> CGTAssessment a
_taCGTAssessment (\TaxAssessment a
s CGTAssessment a
b -> TaxAssessment a
s { _taCGTAssessment :: CGTAssessment a
_taCGTAssessment = CGTAssessment a
b })

privateHealthInsuranceRebateAdjustment :: Lens' (TaxAssessment a) (Money a)
privateHealthInsuranceRebateAdjustment :: forall a. Lens' (TaxAssessment a) (Money a)
privateHealthInsuranceRebateAdjustment = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. TaxAssessment a -> Money a
_phiAdj (\TaxAssessment a
s Money a
b -> TaxAssessment a
s { _phiAdj :: Money a
_phiAdj = Money a
b })

-- | What is the balance of the assessment?  Positive means a
-- refund (tax withheld exceeds obligation), negative means a bill.
taxBalance :: Num a => Getter (TaxAssessment a) (Money a)
taxBalance :: forall a. Num a => Getter (TaxAssessment a) (Money a)
taxBalance = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a b. (a -> b) -> a -> b
$ \TaxAssessment a
a ->
  forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall {k} (a :: k -> *) (b :: k) c.
HasTaxWithheld a b c =>
Getter (a b) (Money c)
taxWithheld TaxAssessment a
a
  forall a. Num a => Money a -> Money a -> Money a
$-$ forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Getter (TaxAssessment a) (Money a)
taxDue TaxAssessment a
a
  forall a. Num a => Money a -> Money a -> Money a
$-$ forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Getter (TaxAssessment a) (Money a)
medicareLevyDue TaxAssessment a
a
  forall a. Num a => Money a -> Money a -> Money a
$-$ forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (TaxAssessment a) (Money a)
privateHealthInsuranceRebateAdjustment TaxAssessment a
a
  forall a. Num a => Money a -> Money a -> Money a
$+$ forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Getter (TaxAssessment a) (Money a)
taxCreditsAndOffsets TaxAssessment a
a

instance (Num a, Eq a) => HasCapitalLossCarryForward TaxAssessment a where
  capitalLossCarryForward :: Lens' (TaxAssessment a) (Money a)
capitalLossCarryForward = forall a. Lens' (TaxAssessment a) (CGTAssessment a)
taxCGTAssessment forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (a :: * -> *) b.
HasCapitalLossCarryForward a b =>
Lens' (a b) (Money b)
capitalLossCarryForward


-- | Consolidated individual tax rate incorporating
-- HELP and SFSS repayments
-- (if applicable) and automatic offsets (e.g. LITO, LMITO).
individualTax
  :: (Fractional a, Ord a)
  => TaxTables y a
  -> Tax (Money a) (Money a)
individualTax :: forall {k} a (y :: k).
(Fractional a, Ord a) =>
TaxTables y a -> Tax (Money a) (Money a)
individualTax TaxTables y a
table =
  forall a b. Ord a => Tax b a -> Tax b a -> Tax b a
greaterOf forall a. Monoid a => a
mempty (forall {k} (y :: k) a. TaxTables y a -> Tax (Money a) (Money a)
ttIndividualIncomeTax TaxTables y a
table forall a. Semigroup a => a -> a -> a
<> forall {k} (y :: k) a. TaxTables y a -> Tax (Money a) (Money a)
ttAdditional TaxTables y a
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)
studyAndTrainingLoanRepayment :: forall a (y :: Year).
(Fractional a, Ord a) =>
TaxTables y a -> TaxReturnInfo y a -> Tax (Money a) (Money a)
studyAndTrainingLoanRepayment TaxTables y a
table TaxReturnInfo y a
info =
  forall a b. Ord a => a -> Tax b a -> Tax b a
limit (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Money a)
helpBalance TaxReturnInfo y a
info) (forall {k} (y :: k) a. TaxTables y a -> Tax (Money a) (Money a)
ttHelp TaxTables y a
table)
  forall a. Semigroup a => a -> a -> a
<> forall a b. Ord a => a -> Tax b a -> Tax b a
limit (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Money a)
sfssBalance TaxReturnInfo y a
info) (forall {k} (y :: k) a. TaxTables y a -> Tax (Money a) (Money a)
ttSfss TaxTables y a
table)

-- | Medicare levy + surcharge
medicareLevyTax
  :: (DaysInYear y, Fractional a)
  => TaxTables y a
  -> TaxReturnInfo y a
  -> Tax (Money a) (Money a)    -- grand unified individual income tax
medicareLevyTax :: forall (y :: Year) a.
(DaysInYear y, Fractional a) =>
TaxTables y a -> TaxReturnInfo y a -> Tax (Money a) (Money a)
medicareLevyTax TaxTables y a
table TaxReturnInfo y a
info =
  let
    ml :: Tax (Money a) (Money a)
ml = forall {k} (y :: k) a. TaxTables y a -> Tax (Money a) (Money a)
ttMedicareLevy TaxTables y a
table
    mls :: Tax (Money a) (Money a)
mls = forall {k} (y :: k) a. TaxTables y a -> Tax (Money a) (Money a)
ttMedicareLevySurcharge TaxTables y a
table
    mlsFrac :: a
mlsFrac = a
1 forall a. Num a => a -> a -> a
- forall (a :: Year) frac.
(DaysInYear a, Fractional frac) =>
Days a -> frac
getFraction (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Days y)
mlsExemption TaxReturnInfo y a
info)
  in
    -- TODO medicare levy exemption
    Tax (Money a) (Money a)
ml
    -- FIXME income for MLS purposes includes
    -- fringe benefits; family thresholds apply
    forall a. Semigroup a => a -> a -> a
<> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. Num a => Money a -> a -> Money a
$* a
mlsFrac) Tax (Money a) (Money a)
mls

-- | Taxable income
instance (RealFrac a) => HasIncome (TaxReturnInfo y) a a where
  income :: Getter (TaxReturnInfo y a) (Money a)
income = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a b. (a -> b) -> a -> b
$ \TaxReturnInfo y a
info ->
    let
      cf :: Money a
cf = forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall (a :: * -> *) b.
HasCapitalLossCarryForward a b =>
Lens' (a b) (Money b)
capitalLossCarryForward TaxReturnInfo y a
info
      gross :: Money a
gross = forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap forall a. RealFrac a => Money a -> Money a
wholeDollars
        [ forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (forall (y :: Year) a. Lens' (TaxReturnInfo y a) [PaymentSummary a]
paymentSummaries forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {k} (a :: k -> *) (b :: k) c.
HasIncome a b c =>
Getter (a b) (Money c)
income) TaxReturnInfo y a
info
        , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (forall (y :: Year) a.
Lens' (TaxReturnInfo y a) (GrossAndWithheld a)
interest forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {k} (a :: k -> *) (b :: k) c.
HasIncome a b c =>
Getter (a b) (Money c)
income) TaxReturnInfo y a
info
        , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (forall (y :: Year) a. Lens' (TaxReturnInfo y a) [Dividend a]
dividends forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {k} (a :: k -> *) (b :: k) c.
HasIncome a b c =>
Getter (a b) (Money c)
income) TaxReturnInfo y a
info
        , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (forall (y :: Year) a. Lens' (TaxReturnInfo y a) (ESSStatement a)
ess forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {k} (a :: k -> *) (b :: k) c.
HasIncome a b c =>
Getter (a b) (Money c)
income) TaxReturnInfo y a
info
        , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (forall (y :: Year) a. Lens' (TaxReturnInfo y a) [CGTEvent a]
cgtEvents forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to (forall a (t :: * -> *).
(Fractional a, Ord a, Foldable t) =>
Money a -> t (CGTEvent a) -> CGTAssessment a
assessCGTEvents Money a
cf) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => Getter (CGTAssessment a) (Money a)
cgtNetGain) TaxReturnInfo y a
info
        , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Money a)
foreignIncome TaxReturnInfo y a
info
        ]
    in
      forall a. RealFrac a => Money a -> Money a
wholeDollars (Money a
gross forall a. Num a => Money a -> Money a -> Money a
$-$ forall s (m :: * -> *) r a.
MonadReader s m =>
LensLike' (Const r) s a -> (a -> r) -> m r
views forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Deductions a)
deductions forall a. (Num a, Ord a) => Deductions a -> Money a
totalDeductions TaxReturnInfo y a
info)

instance (Num a) => HasTaxWithheld (TaxReturnInfo y) a a where
  taxWithheld :: Getter (TaxReturnInfo y a) (Money a)
taxWithheld = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a b. (a -> b) -> a -> b
$ \TaxReturnInfo y a
info ->
    forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (forall (y :: Year) a. Lens' (TaxReturnInfo y a) [PaymentSummary a]
paymentSummaries forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {k} (a :: k -> *) (b :: k) c.
HasTaxWithheld a b c =>
Getter (a b) (Money c)
taxWithheld) TaxReturnInfo y a
info
    forall a. Semigroup a => a -> a -> a
<> forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (forall (y :: Year) a.
Lens' (TaxReturnInfo y a) (GrossAndWithheld a)
interest forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {k} (a :: k -> *) (b :: k) c.
HasTaxWithheld a b c =>
Getter (a b) (Money c)
taxWithheld) TaxReturnInfo y a
info

-- | Assess a tax return, given tax tables and tax return info.
assessTax
  :: (DaysInYear y, RealFrac a)
  => TaxTables y a -> TaxReturnInfo y a -> TaxAssessment a
assessTax :: forall (y :: Year) a.
(DaysInYear y, RealFrac a) =>
TaxTables y a -> TaxReturnInfo y a -> TaxAssessment a
assessTax TaxTables y a
tables TaxReturnInfo y a
info =
  let
    cg :: CGTAssessment a
cg = forall a (t :: * -> *).
(Fractional a, Ord a, Foldable t) =>
Money a -> t (CGTEvent a) -> CGTAssessment a
assessCGTEvents
          (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall (a :: * -> *) b.
HasCapitalLossCarryForward a b =>
Lens' (a b) (Money b)
capitalLossCarryForward TaxReturnInfo y a
info) (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall (y :: Year) a. Lens' (TaxReturnInfo y a) [CGTEvent a]
cgtEvents TaxReturnInfo y a
info)
    taxable :: Money a
taxable = forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall {k} (a :: k -> *) (b :: k) c.
HasIncome a b c =>
Getter (a b) (Money c)
income TaxReturnInfo y a
info
    due :: Money a
due = forall a b. Tax a b -> a -> b
getTax (forall {k} a (y :: k).
(Fractional a, Ord a) =>
TaxTables y a -> Tax (Money a) (Money a)
individualTax TaxTables y a
tables) Money a
taxable
    studyRepayment :: Money a
studyRepayment = forall a b. Tax a b -> a -> b
getTax (forall a (y :: Year).
(Fractional a, Ord a) =>
TaxTables y a -> TaxReturnInfo y a -> Tax (Money a) (Money a)
studyAndTrainingLoanRepayment TaxTables y a
tables TaxReturnInfo y a
info) Money a
taxable
    mlAndMLS :: Money a
mlAndMLS = forall a b. Tax a b -> a -> b
getTax (forall (y :: Year) a.
(DaysInYear y, Fractional a) =>
TaxTables y a -> TaxReturnInfo y a -> Tax (Money a) (Money a)
medicareLevyTax TaxTables y a
tables TaxReturnInfo y a
info) Money a
taxable

    incomeForSurchargePurposes :: Money a
incomeForSurchargePurposes =
      Money a
taxable
      -- TODO reportable fringe benefits
      -- TODO net investment losses
      forall a. Semigroup a => a -> a -> a
<> forall a s. Getting a s a -> s -> a
foldOf (forall (y :: Year) a. Lens' (TaxReturnInfo y a) [PaymentSummary a]
paymentSummaries forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a. PaymentSummary a -> Money a
reportableEmployerSuperannuationContributions) TaxReturnInfo y a
info

    spouseIncomeForSurchargePurposes :: Maybe (Money a)
spouseIncomeForSurchargePurposes =
      forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (SpouseDetails a) (Money a)
spouseTaxableIncome) (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall (y :: Year) a.
Lens' (TaxReturnInfo y a) (Maybe (SpouseDetails a))
spouseDetails TaxReturnInfo y a
info)

    phiAdj :: Money a
phiAdj = forall a.
RealFrac a =>
Money a
-> Maybe (Money a)
-> Integer
-> PrivateHealthInsuranceRebateRates a
-> [PrivateHealthInsurancePolicyDetail a]
-> Money a
assessExcessPrivateHealthRebate
      Money a
incomeForSurchargePurposes
      Maybe (Money a)
spouseIncomeForSurchargePurposes
      (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (forall (y :: Year) a. Lens' (TaxReturnInfo y a) (IncomeTests a)
incomeTests forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Lens' (IncomeTests a) Integer
dependentChildren) TaxReturnInfo y a
info)
      (forall {k} (y :: k) a.
TaxTables y a -> PrivateHealthInsuranceRebateRates a
ttPHIRebateRates TaxTables y a
tables)
      (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall (y :: Year) a.
Lens' (TaxReturnInfo y a) [PrivateHealthInsurancePolicyDetail a]
privateHealthInsurancePolicyDetails TaxReturnInfo y a
info)

    foreignIncomeTaxOffsetLimit :: Money a
foreignIncomeTaxOffsetLimit =
      let
        step1 :: Money a
step1 = Money a
due forall a. Semigroup a => a -> a -> a
<> Money a
mlAndMLS
        step2 :: Money a
step2 =
          let
            info' :: TaxReturnInfo y a
info' = TaxReturnInfo y a
info forall a b. a -> (a -> b) -> b
& forall s t a b. ASetter s t a b -> b -> s -> t
set forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Money a)
foreignIncome forall a. Monoid a => a
mempty
            taxable' :: Money a
taxable' = forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall {k} (a :: k -> *) (b :: k) c.
HasIncome a b c =>
Getter (a b) (Money c)
income TaxReturnInfo y a
info' forall a. Semigroup a => a -> a -> a
<> forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Deductions a)
deductions forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Lens' (Deductions a) (Money a)
foreignIncomeDeductions) TaxReturnInfo y a
info'
            due' :: Money a
due' = forall a b. Tax a b -> a -> b
getTax (forall {k} a (y :: k).
(Fractional a, Ord a) =>
TaxTables y a -> Tax (Money a) (Money a)
individualTax TaxTables y a
tables) Money a
taxable'
            mlAndMLS' :: Money a
mlAndMLS' = forall a b. Tax a b -> a -> b
getTax (forall (y :: Year) a.
(DaysInYear y, Fractional a) =>
TaxTables y a -> TaxReturnInfo y a -> Tax (Money a) (Money a)
medicareLevyTax TaxTables y a
tables TaxReturnInfo y a
info') Money a
taxable'
          in
            Money a
due' forall a. Semigroup a => a -> a -> a
<> Money a
mlAndMLS'
        step3 :: Money a
step3 = Money a
step1 forall a. Num a => Money a -> Money a -> Money a
$-$ Money a
step2
      in
        forall a. Ord a => a -> a -> a
max (forall num. num -> Money num
Money a
1000) Money a
step3

    frankingCredit :: Money a
frankingCredit =
      forall a. RealFrac a => Money a -> Money a
wholeDollars
      forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap forall a. RealFrac a => Dividend a -> Money a
dividendFrankingCredit (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall (y :: Year) a. Lens' (TaxReturnInfo y a) [Dividend a]
dividends TaxReturnInfo y a
info)
    off :: Money a
off =
      forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Offsets a)
offsets forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Lens' (Offsets a) (Money a)
spouseContributionOffset) TaxReturnInfo y a
info
      forall a. Semigroup a => a -> a -> a
<> forall a. Ord a => a -> a -> a
min (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Offsets a)
offsets forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Lens' (Offsets a) (Money a)
foreignTaxOffset) TaxReturnInfo y a
info) Money a
foreignIncomeTaxOffsetLimit
      forall a. Semigroup a => a -> a -> a
<> forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (forall (y :: Year) a. Lens' (TaxReturnInfo y a) (Offsets a)
offsets forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Lens' (Offsets a) (Money a)
paygInstalments) TaxReturnInfo y a
info

  in
    forall a.
Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> CGTAssessment a
-> Money a
-> TaxAssessment a
TaxAssessment
      Money a
taxable
      (Money a
due forall a. Semigroup a => a -> a -> a
<> Money a
studyRepayment)
      Money a
mlAndMLS
      (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall {k} (a :: k -> *) (b :: k) c.
HasTaxWithheld a b c =>
Getter (a b) (Money c)
taxWithheld TaxReturnInfo y a
info)
      (Money a
frankingCredit forall a. Semigroup a => a -> a -> a
<> Money a
off)
      CGTAssessment a
cg
      Money a
phiAdj

-- | Australian Business Number
type ABN = String

-- | PAYG payment summary - individual non-business
data PaymentSummary a = PaymentSummary
  { forall a. PaymentSummary a -> ABN
summaryABN :: ABN
  , forall a. PaymentSummary a -> Money a
summaryGross :: Money a
  , forall a. PaymentSummary a -> Money a
summaryWithheld :: Money a
  , forall a. PaymentSummary a -> Money a
reportableEmployerSuperannuationContributions :: Money a
  }

-- | Gross income
instance HasIncome PaymentSummary a a where
  income :: Getter (PaymentSummary a) (Money a)
income = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a. PaymentSummary a -> Money a
summaryGross

instance HasTaxWithheld PaymentSummary a a where
  taxWithheld :: Getter (PaymentSummary a) (Money a)
taxWithheld = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a. PaymentSummary a -> Money a
summaryWithheld

-- | A proportion is a non-negative number in interval @[0,1]@.
-- Use 'proportion' to construct.
newtype Proportion a = Proportion
  { forall a. Proportion a -> a
getProportion :: a -- ^ Return underlying figure, which is in interval @[0,1]@
  }
  deriving (Int -> Proportion a -> ShowS
forall a. Show a => Int -> Proportion a -> ShowS
forall a. Show a => [Proportion a] -> ShowS
forall a. Show a => Proportion a -> ABN
forall a.
(Int -> a -> ShowS) -> (a -> ABN) -> ([a] -> ShowS) -> Show a
showList :: [Proportion a] -> ShowS
$cshowList :: forall a. Show a => [Proportion a] -> ShowS
show :: Proportion a -> ABN
$cshow :: forall a. Show a => Proportion a -> ABN
showsPrec :: Int -> Proportion a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Proportion a -> ShowS
Show, Proportion a -> Proportion a -> Bool
forall a. Eq a => Proportion a -> Proportion a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Proportion a -> Proportion a -> Bool
$c/= :: forall a. Eq a => Proportion a -> Proportion a -> Bool
== :: Proportion a -> Proportion a -> Bool
$c== :: forall a. Eq a => Proportion a -> Proportion a -> Bool
Eq, Proportion a -> Proportion a -> Bool
Proportion a -> Proportion a -> Ordering
Proportion a -> Proportion a -> Proportion a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (Proportion a)
forall a. Ord a => Proportion a -> Proportion a -> Bool
forall a. Ord a => Proportion a -> Proportion a -> Ordering
forall a. Ord a => Proportion a -> Proportion a -> Proportion a
min :: Proportion a -> Proportion a -> Proportion a
$cmin :: forall a. Ord a => Proportion a -> Proportion a -> Proportion a
max :: Proportion a -> Proportion a -> Proportion a
$cmax :: forall a. Ord a => Proportion a -> Proportion a -> Proportion a
>= :: Proportion a -> Proportion a -> Bool
$c>= :: forall a. Ord a => Proportion a -> Proportion a -> Bool
> :: Proportion a -> Proportion a -> Bool
$c> :: forall a. Ord a => Proportion a -> Proportion a -> Bool
<= :: Proportion a -> Proportion a -> Bool
$c<= :: forall a. Ord a => Proportion a -> Proportion a -> Bool
< :: Proportion a -> Proportion a -> Bool
$c< :: forall a. Ord a => Proportion a -> Proportion a -> Bool
compare :: Proportion a -> Proportion a -> Ordering
$ccompare :: forall a. Ord a => Proportion a -> Proportion a -> Ordering
Ord)

-- | Construct a proportion.  Out of range numbers are clamped
-- to @0@ or @1@ (no runtime errors).
proportion :: (Ord a, Num a) => a -> Proportion a
proportion :: forall a. (Ord a, Num a) => a -> Proportion a
proportion = forall a. a -> Proportion a
Proportion forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => a -> a -> a
max a
0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => a -> a -> a
min a
1

-- | Dividend payment.  Records net income, franked portion
-- and amount of tax withheld.
data Dividend a = Dividend
  { forall a. Dividend a -> ABN
dividendSource :: String
  , forall a. Dividend a -> ABN
dividendDate :: String  -- FUTURE better type
  , forall a. Dividend a -> Money a
dividendNetPayment :: Money a
  , forall a. Dividend a -> Proportion a
dividendFrankedPortion :: Proportion a  -- ^ Franked ratio (@1@ = 100%)
  , forall a. Dividend a -> Money a
dividendTaxWithheld :: Money a
  }
  deriving (Int -> Dividend a -> ShowS
forall a. Show a => Int -> Dividend a -> ShowS
forall a. Show a => [Dividend a] -> ShowS
forall a. Show a => Dividend a -> ABN
forall a.
(Int -> a -> ShowS) -> (a -> ABN) -> ([a] -> ShowS) -> Show a
showList :: [Dividend a] -> ShowS
$cshowList :: forall a. Show a => [Dividend a] -> ShowS
show :: Dividend a -> ABN
$cshow :: forall a. Show a => Dividend a -> ABN
showsPrec :: Int -> Dividend a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Dividend a -> ShowS
Show)

instance (RealFrac a) => HasTaxWithheld Dividend a a where
  taxWithheld :: Getter (Dividend a) (Money a)
taxWithheld = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to (forall a. RealFrac a => Money a -> Money a
roundCents forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Dividend a -> Money a
dividendTaxWithheld)

-- | Calculate the franking credit for a dividend
--
dividendFrankingCredit :: (RealFrac a) => Dividend a -> Money a
dividendFrankingCredit :: forall a. RealFrac a => Dividend a -> Money a
dividendFrankingCredit Dividend a
d = forall a. RealFrac a => Money a -> Money a
roundCents forall a b. (a -> b) -> a -> b
$
  (forall a. Proportion a -> a
getProportion forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Dividend a -> Proportion a
dividendFrankedPortion) Dividend a
d
  forall a. Num a => a -> Money a -> Money a
*$ forall a b. Tax a b -> a -> b
getTax forall a. Fractional a => Tax (Money a) (Money a)
corporateTax (forall a. Dividend a -> Money a
dividendNetPayment Dividend a
d forall a. Num a => Money a -> a -> Money a
$* (a
1 forall a. Fractional a => a -> a -> a
/ a
0.7))

-- | Attributable income
instance (RealFrac a) => HasIncome Dividend a a where
  income :: Getter (Dividend a) (Money a)
income = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a b. (a -> b) -> a -> b
$ \Dividend a
d ->
    forall a. RealFrac a => Money a -> Money a
roundCents (forall a. Dividend a -> Money a
dividendNetPayment Dividend a
d)
    forall a. Semigroup a => a -> a -> a
<> forall a. RealFrac a => Dividend a -> Money a
dividendFrankingCredit Dividend a
d
    forall a. Semigroup a => a -> a -> a
<> forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall {k} (a :: k -> *) (b :: k) c.
HasTaxWithheld a b c =>
Getter (a b) (Money c)
taxWithheld Dividend a
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
  { forall a. Offsets a -> Money a
_spouseOffset :: Money a
  , forall a. Offsets a -> Money a
_foreignTaxOffset :: Money a
  , forall a. Offsets a -> Money a
_paygInstalments :: Money a
  }

instance Num a => Semigroup (Offsets a) where
  Offsets Money a
a Money a
b Money a
c <> :: Offsets a -> Offsets a -> Offsets a
<> Offsets Money a
a' Money a
b' Money a
c' = forall a. Money a -> Money a -> Money a -> Offsets a
Offsets (Money a
a forall a. Semigroup a => a -> a -> a
<> Money a
a') (Money a
b forall a. Semigroup a => a -> a -> a
<> Money a
b') (Money a
c forall a. Semigroup a => a -> a -> a
<> Money a
c')

instance Num a => Monoid (Offsets a) where
  mempty :: Offsets a
mempty = forall a. Money a -> Money a -> Money a -> Offsets a
Offsets forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty
  mappend :: Offsets a -> Offsets a -> Offsets a
mappend = forall a. Semigroup a => a -> a -> a
(<>)

-- | Spouse contribution offset.  Maximum of /$540/ (not enforced).
spouseContributionOffset :: Lens' (Offsets a) (Money a)
spouseContributionOffset :: forall a. Lens' (Offsets a) (Money a)
spouseContributionOffset = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Offsets a -> Money a
_spouseOffset (\Offsets a
s Money a
b -> Offsets a
s { _spouseOffset :: Money a
_spouseOffset = Money a
b })

-- | Offset for tax paid on foreign income.
foreignTaxOffset :: Lens' (Offsets a) (Money a)
foreignTaxOffset :: forall a. Lens' (Offsets a) (Money a)
foreignTaxOffset = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Offsets a -> Money a
_foreignTaxOffset (\Offsets a
s Money a
b -> Offsets a
s { _foreignTaxOffset :: Money a
_foreignTaxOffset = Money a
b })

paygInstalments :: Lens' (Offsets a) (Money a)
paygInstalments :: forall a. Lens' (Offsets a) (Money a)
paygInstalments = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Offsets a -> Money a
_paygInstalments (\Offsets a
s Money a
b -> Offsets a
s { _paygInstalments :: Money a
_paygInstalments = Money a
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
  { forall a. Deductions a -> Money a
_workRelatedCarExpenses :: Money a
  , forall a. Deductions a -> Money a
_workRelatedTravelExpenses :: Money a
  , forall a. Deductions a -> Money a
_workRelatedClothingLaundryAndDryCleaningExpenses :: Money a
  , forall a. Deductions a -> Money a
_workRelatedSelfEducationExpenses :: Money a
  , forall a. Deductions a -> Money a
_otherWorkRelatedExpenses :: Money a
  , forall a. Deductions a -> Money a
_lowValuePoolDeduction :: Money a
  , forall a. Deductions a -> Money a
_interestDeductions :: Money a
  , forall a. Deductions a -> Money a
_dividendDeductions :: Money a
  , forall a. Deductions a -> Money a
_giftsOrDonations :: Money a
  , forall a. Deductions a -> Money a
_costOfManagingTaxAffairs :: Money a
  , forall a. Deductions a -> Money a
_deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity :: Money a
  , forall a. Deductions a -> Money a
_personalSuperannuationContributions :: Money a
  , forall a. Deductions a -> Money a
_deductionForProjectPool :: Money a
  , forall a. Deductions a -> Money a
_forestryManagedInvestmentSchemeDeduction :: Money a
  , forall a. Deductions a -> Money a
_otherDeductions :: Money a
  , forall a. Deductions a -> Money a
_foreignIncomeDeductions :: Money a
  }

instance Num a => Semigroup (Deductions a) where
  Deductions Money a
a Money a
b Money a
c Money a
d Money a
e Money a
f Money a
g Money a
h Money a
i Money a
j Money a
k Money a
l Money a
m Money a
n Money a
o Money a
p
    <> :: Deductions a -> Deductions a -> Deductions a
<> Deductions Money a
a' Money a
b' Money a
c' Money a
d' Money a
e' Money a
f' Money a
g' Money a
h' Money a
i' Money a
j' Money a
k' Money a
l' Money a
m' Money a
n' Money a
o' Money a
p'
      = forall a.
Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Deductions a
Deductions (Money a
a forall a. Semigroup a => a -> a -> a
<> Money a
a') (Money a
b forall a. Semigroup a => a -> a -> a
<> Money a
b') (Money a
c forall a. Semigroup a => a -> a -> a
<> Money a
c') (Money a
d forall a. Semigroup a => a -> a -> a
<> Money a
d') (Money a
e forall a. Semigroup a => a -> a -> a
<> Money a
e') (Money a
f forall a. Semigroup a => a -> a -> a
<> Money a
f') (Money a
g forall a. Semigroup a => a -> a -> a
<> Money a
g') (Money a
h forall a. Semigroup a => a -> a -> a
<> Money a
h')
                   (Money a
i forall a. Semigroup a => a -> a -> a
<> Money a
i') (Money a
j forall a. Semigroup a => a -> a -> a
<> Money a
j') (Money a
k forall a. Semigroup a => a -> a -> a
<> Money a
k') (Money a
l forall a. Semigroup a => a -> a -> a
<> Money a
l') (Money a
m forall a. Semigroup a => a -> a -> a
<> Money a
m') (Money a
n forall a. Semigroup a => a -> a -> a
<> Money a
n') (Money a
o forall a. Semigroup a => a -> a -> a
<> Money a
o') (Money a
p forall a. Semigroup a => a -> a -> a
<> Money a
p')

instance Num a => Monoid (Deductions a) where
  mempty :: Deductions a
mempty = forall a.
Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Deductions a
Deductions forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty
                      forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty

-- | Sum the deductions.  Negative components are ignored.
totalDeductions :: (Num a, Ord a) => Deductions a -> Money a
totalDeductions :: forall a. (Num a, Ord a) => Deductions a -> Money a
totalDeductions Deductions a
a =
  forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (forall a. Ord a => a -> a -> a
max forall a. Monoid a => a
mempty)
    [ forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
workRelatedCarExpenses Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
workRelatedTravelExpenses Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
workRelatedClothingLaundryAndDryCleaningExpenses Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
workRelatedSelfEducationExpenses Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
otherWorkRelatedExpenses Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
lowValuePoolDeduction Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
interestDeductions Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
dividendDeductions Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
giftsOrDonations Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
costOfManagingTaxAffairs Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
personalSuperannuationContributions Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
deductionForProjectPool Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
forestryManagedInvestmentSchemeDeduction Deductions a
a
    , forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (Deductions a) (Money a)
otherDeductions Deductions a
a
    ]

-- | __D1__ Work-related car expenses
workRelatedCarExpenses :: Lens' (Deductions a) (Money a)
workRelatedCarExpenses :: forall a. Lens' (Deductions a) (Money a)
workRelatedCarExpenses =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Deductions a -> Money a
_workRelatedCarExpenses (\Deductions a
s Money a
b -> Deductions a
s { _workRelatedCarExpenses :: Money a
_workRelatedCarExpenses = Money a
b })

-- | __D2__ Work-related travel expenses
workRelatedTravelExpenses :: Lens' (Deductions a) (Money a)
workRelatedTravelExpenses :: forall a. Lens' (Deductions a) (Money a)
workRelatedTravelExpenses =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Deductions a -> Money a
_workRelatedTravelExpenses (\Deductions a
s Money a
b -> Deductions a
s { _workRelatedTravelExpenses :: Money a
_workRelatedTravelExpenses = Money a
b })

-- | __D3__ Work-related clothing, laundry and dry-cleaning expenses
workRelatedClothingLaundryAndDryCleaningExpenses :: Lens' (Deductions a) (Money a)
workRelatedClothingLaundryAndDryCleaningExpenses :: forall a. Lens' (Deductions a) (Money a)
workRelatedClothingLaundryAndDryCleaningExpenses =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens
    forall a. Deductions a -> Money a
_workRelatedClothingLaundryAndDryCleaningExpenses
    (\Deductions a
s Money a
b -> Deductions a
s { _workRelatedClothingLaundryAndDryCleaningExpenses :: Money a
_workRelatedClothingLaundryAndDryCleaningExpenses = Money a
b })

-- | __D4__ Work-related self-education expenses
workRelatedSelfEducationExpenses :: Lens' (Deductions a) (Money a)
workRelatedSelfEducationExpenses :: forall a. Lens' (Deductions a) (Money a)
workRelatedSelfEducationExpenses =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Deductions a -> Money a
_workRelatedSelfEducationExpenses (\Deductions a
s Money a
b -> Deductions a
s { _workRelatedSelfEducationExpenses :: Money a
_workRelatedSelfEducationExpenses = Money a
b })

-- | __D5__ Other work-related expenses
otherWorkRelatedExpenses :: Lens' (Deductions a) (Money a)
otherWorkRelatedExpenses :: forall a. Lens' (Deductions a) (Money a)
otherWorkRelatedExpenses =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Deductions a -> Money a
_otherWorkRelatedExpenses (\Deductions a
s Money a
b -> Deductions a
s { _otherWorkRelatedExpenses :: Money a
_otherWorkRelatedExpenses = Money a
b })

-- | __D6__ Low-value pool deduction
lowValuePoolDeduction :: Lens' (Deductions a) (Money a)
lowValuePoolDeduction :: forall a. Lens' (Deductions a) (Money a)
lowValuePoolDeduction =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Deductions a -> Money a
_lowValuePoolDeduction (\Deductions a
s Money a
b -> Deductions a
s { _lowValuePoolDeduction :: Money a
_lowValuePoolDeduction = Money a
b })

-- | __D7__ Interest deductions
interestDeductions :: Lens' (Deductions a) (Money a)
interestDeductions :: forall a. Lens' (Deductions a) (Money a)
interestDeductions =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Deductions a -> Money a
_interestDeductions (\Deductions a
s Money a
b -> Deductions a
s { _interestDeductions :: Money a
_interestDeductions = Money a
b })

-- | __D8__ Dividend deductions
dividendDeductions :: Lens' (Deductions a) (Money a)
dividendDeductions :: forall a. Lens' (Deductions a) (Money a)
dividendDeductions =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Deductions a -> Money a
_dividendDeductions (\Deductions a
s Money a
b -> Deductions a
s { _dividendDeductions :: Money a
_dividendDeductions = Money a
b })

-- | __D9__ Gifts or donations
giftsOrDonations :: Lens' (Deductions a) (Money a)
giftsOrDonations :: forall a. Lens' (Deductions a) (Money a)
giftsOrDonations =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Deductions a -> Money a
_giftsOrDonations (\Deductions a
s Money a
b -> Deductions a
s { _giftsOrDonations :: Money a
_giftsOrDonations = Money a
b })

-- | __D10__ Cost of managing tax affairs
costOfManagingTaxAffairs :: Lens' (Deductions a) (Money a)
costOfManagingTaxAffairs :: forall a. Lens' (Deductions a) (Money a)
costOfManagingTaxAffairs =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Deductions a -> Money a
_costOfManagingTaxAffairs (\Deductions a
s Money a
b -> Deductions a
s { _costOfManagingTaxAffairs :: Money a
_costOfManagingTaxAffairs = Money a
b })

-- | __D11__ Deductible amount of undeducted purchase price of a foreign pension or annuity
deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity :: Lens' (Deductions a) (Money a)
deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity :: forall a. Lens' (Deductions a) (Money a)
deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens
    forall a. Deductions a -> Money a
_deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity 
    (\Deductions a
s Money a
b -> Deductions a
s { _deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity :: Money a
_deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity = Money a
b })

-- | __D12__ Personal superannuation contributions
personalSuperannuationContributions :: Lens' (Deductions a) (Money a)
personalSuperannuationContributions :: forall a. Lens' (Deductions a) (Money a)
personalSuperannuationContributions =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Deductions a -> Money a
_personalSuperannuationContributions (\Deductions a
s Money a
b -> Deductions a
s { _personalSuperannuationContributions :: Money a
_personalSuperannuationContributions = Money a
b })

-- | __D13__ Deduction for project pool
deductionForProjectPool :: Lens' (Deductions a) (Money a)
deductionForProjectPool :: forall a. Lens' (Deductions a) (Money a)
deductionForProjectPool =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Deductions a -> Money a
_deductionForProjectPool (\Deductions a
s Money a
b -> Deductions a
s { _deductionForProjectPool :: Money a
_deductionForProjectPool = Money a
b })

-- | __D14__ Forestry managed investment scheme deduction
forestryManagedInvestmentSchemeDeduction :: Lens' (Deductions a) (Money a)
forestryManagedInvestmentSchemeDeduction :: forall a. Lens' (Deductions a) (Money a)
forestryManagedInvestmentSchemeDeduction =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens
    forall a. Deductions a -> Money a
_forestryManagedInvestmentSchemeDeduction
    (\Deductions a
s Money a
b -> Deductions a
s { _forestryManagedInvestmentSchemeDeduction :: Money a
_forestryManagedInvestmentSchemeDeduction = Money a
b })

-- | __D15__ Other deductions — not claimable at __D1__ to __D14__ or elsewhere
-- in your tax return
otherDeductions :: Lens' (Deductions a) (Money a)
otherDeductions :: forall a. Lens' (Deductions a) (Money a)
otherDeductions =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Deductions a -> Money a
_otherDeductions (\Deductions a
s Money a
b -> Deductions a
s { _otherDeductions :: Money a
_otherDeductions = Money a
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 :: forall a. Lens' (Deductions a) (Money a)
foreignIncomeDeductions =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. Deductions a -> Money a
_foreignIncomeDeductions (\Deductions a
s Money a
b -> Deductions a
s { _foreignIncomeDeductions :: Money a
_foreignIncomeDeductions = Money a
b })


-- | A gross income (first argument) and amount of tax withheld (second argument)
data GrossAndWithheld a = GrossAndWithheld (Money a) (Money a)

instance (Num a) => Semigroup (GrossAndWithheld a) where
  GrossAndWithheld Money a
a Money a
b <> :: GrossAndWithheld a -> GrossAndWithheld a -> GrossAndWithheld a
<> GrossAndWithheld Money a
a' Money a
b' =
    forall a. Money a -> Money a -> GrossAndWithheld a
GrossAndWithheld (Money a
a forall a. Semigroup a => a -> a -> a
<> Money a
a') (Money a
b forall a. Semigroup a => a -> a -> a
<> Money a
b')

instance (Num a) => Monoid (GrossAndWithheld a) where
  mempty :: GrossAndWithheld a
mempty = forall a. Money a -> Money a -> GrossAndWithheld a
GrossAndWithheld forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty
  mappend :: GrossAndWithheld a -> GrossAndWithheld a -> GrossAndWithheld a
mappend = forall a. Semigroup a => a -> a -> a
(<>)

instance HasIncome GrossAndWithheld a a where
  income :: Getter (GrossAndWithheld a) (Money a)
income = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a b. (a -> b) -> a -> b
$ \(GrossAndWithheld Money a
a Money a
_) -> Money a
a

instance HasTaxWithheld GrossAndWithheld a a where
  taxWithheld :: Getter (GrossAndWithheld a) (Money a)
taxWithheld = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a b. (a -> b) -> a -> b
$ \(GrossAndWithheld Money a
_ Money a
a) -> Money a
a


-- | Employee share scheme statement.  Use 'newESSStatement' to construct.
data ESSStatement a = ESSStatement
  { forall a. ESSStatement a -> Money a
_taxedUpfrontReduction :: Money a
  , forall a. ESSStatement a -> Money a
_taxedUpfrontNoReduction :: Money a
  , forall a. ESSStatement a -> Money a
_deferral :: Money a
  , forall a. ESSStatement a -> Money a
_pre2009 :: Money a
  , forall a. ESSStatement a -> Money a
_tfnAmounts :: Money a
  , forall a. ESSStatement a -> Money a
_foreignSourceDiscounts :: Money a
  }

-- | Construct an 'ESSStatement' with all amounts at /zero/.
newESSStatement :: Num a => ESSStatement a
newESSStatement :: forall a. Num a => ESSStatement a
newESSStatement = forall a.
Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> ESSStatement a
ESSStatement forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty

-- | Discount from taxed up front schemes—eligible for reduction.
-- Item __D__ in /Employee share schemes/ section.
essTaxedUpfrontReduction :: Lens' (ESSStatement a) (Money a)
essTaxedUpfrontReduction :: forall a. Lens' (ESSStatement a) (Money a)
essTaxedUpfrontReduction =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. ESSStatement a -> Money a
_taxedUpfrontReduction (\ESSStatement a
s Money a
b -> ESSStatement a
s { _taxedUpfrontReduction :: Money a
_taxedUpfrontReduction = Money a
b })

-- | Discount from taxed up front schemes—not eligible for reduction
-- Item __E__ in /Employee share schemes/ section.
essTaxedUpfrontNoReduction :: Lens' (ESSStatement a) (Money a)
essTaxedUpfrontNoReduction :: forall a. Lens' (ESSStatement a) (Money a)
essTaxedUpfrontNoReduction =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. ESSStatement a -> Money a
_taxedUpfrontNoReduction (\ESSStatement a
s Money a
b -> ESSStatement a
s { _taxedUpfrontNoReduction :: Money a
_taxedUpfrontNoReduction = Money a
b })

-- | Discount from taxed deferral schemes.
-- Item __F__ in /Employee share schemes/ section.
essDeferral :: Lens' (ESSStatement a) (Money a)
essDeferral :: forall a. Lens' (ESSStatement a) (Money a)
essDeferral = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. ESSStatement a -> Money a
_deferral (\ESSStatement a
s Money a
b -> ESSStatement a
s { _deferral :: Money a
_deferral = Money a
b })

-- | discounts on ESS interests acquired pre 1 July 2009 and
-- "cessation time" occurred during the finanical year.
-- Item __G__ in /Employee share schemes/ section.
essPre2009 :: Lens' (ESSStatement a) (Money a)
essPre2009 :: forall a. Lens' (ESSStatement a) (Money a)
essPre2009 = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. ESSStatement a -> Money a
_pre2009 (\ESSStatement a
s Money a
b -> ESSStatement a
s { _pre2009 :: Money a
_pre2009 = Money a
b })

-- | TFN amounts withheld from discounts.
-- Item __C__ in /Employee share schemes/ section.
essTFNAmounts :: Lens' (ESSStatement a) (Money a)
essTFNAmounts :: forall a. Lens' (ESSStatement a) (Money a)
essTFNAmounts = forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. ESSStatement a -> Money a
_tfnAmounts (\ESSStatement a
s Money a
b -> ESSStatement a
s { _tfnAmounts :: Money a
_tfnAmounts = Money a
b })

-- | ESS foreign source discounts
-- Item __A__ in /Employee share schemes/ section.
essForeignSourceDiscounts :: Lens' (ESSStatement a) (Money a)
essForeignSourceDiscounts :: forall a. Lens' (ESSStatement a) (Money a)
essForeignSourceDiscounts =
  forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall a. ESSStatement a -> Money a
_foreignSourceDiscounts (\ESSStatement a
s Money a
b -> ESSStatement a
s { _foreignSourceDiscounts :: Money a
_foreignSourceDiscounts = Money a
b })

-- | __Note:__ does not implement the reduction of taxed up front
-- amounts eligible for reduction.
instance (Num a) => HasIncome ESSStatement a a where
  income :: Getter (ESSStatement a) (Money a)
income = forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a b. (a -> b) -> a -> b
$ \ESSStatement a
s ->
    forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (ESSStatement a) (Money a)
essTaxedUpfrontReduction ESSStatement a
s
    forall a. Semigroup a => a -> a -> a
<> forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (ESSStatement a) (Money a)
essTaxedUpfrontNoReduction ESSStatement a
s
    forall a. Semigroup a => a -> a -> a
<> forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (ESSStatement a) (Money a)
essDeferral ESSStatement a
s
    forall a. Semigroup a => a -> a -> a
<> forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall a. Lens' (ESSStatement a) (Money a)
essPre2009 ESSStatement a
s

instance (Num a) => Semigroup (ESSStatement a) where
  ESSStatement Money a
a Money a
b Money a
c Money a
d Money a
e Money a
f <> :: ESSStatement a -> ESSStatement a -> ESSStatement a
<> ESSStatement Money a
a' Money a
b' Money a
c' Money a
d' Money a
e' Money a
f' =
    forall a.
Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> Money a
-> ESSStatement a
ESSStatement (Money a
a forall a. Semigroup a => a -> a -> a
<> Money a
a') (Money a
b forall a. Semigroup a => a -> a -> a
<> Money a
b') (Money a
c forall a. Semigroup a => a -> a -> a
<> Money a
c') (Money a
d forall a. Semigroup a => a -> a -> a
<> Money a
d') (Money a
e forall a. Semigroup a => a -> a -> a
<> Money a
e') (Money a
f forall a. Semigroup a => a -> a -> a
<> Money a
f')

instance (Num a) => Monoid (ESSStatement a) where
  mempty :: ESSStatement a
mempty = forall a. Num a => ESSStatement a
newESSStatement
  mappend :: ESSStatement a -> ESSStatement a -> ESSStatement a
mappend = forall a. Semigroup a => a -> a -> a
(<>)