tax-ato 2024.1.0.1 → 2025.1
raw patch · 21 files changed
+1927/−306 lines, 21 filesdep ~lensdep ~timePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: lens, time
API changes (from Hackage documentation)
- Data.Tax.ATO: PaymentSummary :: ABN -> Money a -> Money a -> Money a -> PaymentSummary a
- Data.Tax.ATO: [reportableEmployerSuperannuationContributions] :: PaymentSummary a -> Money a
- Data.Tax.ATO: [summaryABN] :: PaymentSummary a -> ABN
- Data.Tax.ATO: [summaryGross] :: PaymentSummary a -> Money a
- Data.Tax.ATO: [summaryWithheld] :: PaymentSummary a -> Money a
- Data.Tax.ATO: data PaymentSummary a
- Data.Tax.ATO: instance (Data.Foldable.Foldable t, Data.Tax.ATO.HasTaxWithheld x a a, GHC.Num.Num a) => Data.Tax.ATO.HasTaxWithheld t (x a) a
- Data.Tax.ATO: instance (GHC.Num.Num a, GHC.Classes.Eq a) => Data.Tax.ATO.CGT.HasCapitalLossCarryForward Data.Tax.ATO.TaxAssessment a
- Data.Tax.ATO: instance Data.Tax.ATO.Common.HasTaxableIncome Data.Tax.ATO.PaymentSummary a a
- Data.Tax.ATO: instance Data.Tax.ATO.HasTaxWithheld Data.Tax.ATO.GrossAndWithheld a a
- Data.Tax.ATO: instance Data.Tax.ATO.HasTaxWithheld Data.Tax.ATO.PaymentSummary a a
- Data.Tax.ATO: instance Data.Tax.ATO.HasTaxWithheld Data.Tax.ATO.TaxAssessment a a
- Data.Tax.ATO: instance GHC.Num.Num a => Data.Tax.ATO.HasTaxWithheld (Data.Tax.ATO.TaxReturnInfo y) a a
- Data.Tax.ATO: instance GHC.Num.Num a => GHC.Base.Monoid (Data.Tax.ATO.ESSStatement a)
- Data.Tax.ATO: instance GHC.Num.Num a => GHC.Base.Semigroup (Data.Tax.ATO.ESSStatement a)
- Data.Tax.ATO: instance GHC.Real.RealFrac a => Data.Tax.ATO.HasTaxWithheld Data.Tax.ATO.Dividend a a
- Data.Tax.ATO: taxCreditsAndOffsets :: Getter (TaxAssessment a) (Money a)
- Data.Tax.ATO: type ABN = String
- Data.Tax.ATO.CGT: CGTAssessment :: Money a -> CGTNetGainOrLoss a -> CGTAssessment a
- Data.Tax.ATO.CGT: CGTLoss :: Money a -> CGTNetGainOrLoss a
- Data.Tax.ATO.CGT: CGTNetGain :: Money a -> CGTNetGainOrLoss a
- Data.Tax.ATO.CGT: cgtNetGainOrLoss :: Lens' (CGTAssessment a) (CGTNetGainOrLoss a)
- Data.Tax.ATO.CGT: data CGTNetGainOrLoss a
- Data.Tax.ATO.CGT: instance (GHC.Num.Num a, GHC.Classes.Eq a) => Data.Tax.ATO.CGT.HasCapitalLossCarryForward Data.Tax.ATO.CGT.CGTAssessment a
- Data.Tax.ATO.CGT: instance (GHC.Num.Num a, GHC.Classes.Eq a) => Data.Tax.ATO.CGT.HasCapitalLossCarryForward Data.Tax.ATO.CGT.CGTNetGainOrLoss a
- Data.Tax.ATO.CGT: instance Data.Tax.ATO.CGT.HasCapitalGain Data.Tax.ATO.CGT.CGTAssessment a a
- Data.Tax.ATO.CGT: instance GHC.Base.Functor Data.Tax.ATO.CGT.CGTNetGainOrLoss
- Data.Tax.ATO.CGT: instance GHC.Show.Show a => GHC.Show.Show (Data.Tax.ATO.CGT.CGTAssessment a)
- Data.Tax.ATO.CGT: instance GHC.Show.Show a => GHC.Show.Show (Data.Tax.ATO.CGT.CGTNetGainOrLoss a)
- Data.Tax.ATO.CGT: netCapitalGainOrLoss :: (Fractional a, Ord a, Foldable t) => Money a -> t (CGTEvent a) -> CGTNetGainOrLoss a
- Data.Tax.ATO.Common: [ttMedicareLevy] :: TaxTables y a -> Tax (Money a) (Money a)
- Data.Tax.ATO.Pretty: summariseCGTAssessment :: CGTAssessment Rational -> Doc
+ Data.Tax.ATO: applyCentsPerKilometreMethod :: forall {k} (y :: k) a. (HasCentsPerKilometreMethod y, Fractional a, Ord a) => a -> Money a
+ Data.Tax.ATO: applyFixedRateMethod :: forall {k} (y :: k) a. (HasFixedRateMethod y, Fractional a) => a -> Money a
+ Data.Tax.ATO: applyFixedRateMethodPre2023 :: forall {k} (y :: k) a. (HasFixedRateMethodPre2023 y, Fractional a) => a -> Money a
+ Data.Tax.ATO: applyShortcutMethod :: forall {k} (y :: k) a. (HasShortcutMethod y, Fractional a) => a -> Money a
+ Data.Tax.ATO: class HasCentsPerKilometreMethod (y :: k)
+ Data.Tax.ATO: class HasFixedRateMethod (y :: k)
+ Data.Tax.ATO: class HasFixedRateMethodPre2023 (y :: k)
+ Data.Tax.ATO: class HasShortcutMethod (y :: k)
+ Data.Tax.ATO: class HasTaxableIncome (a :: k -> Type) (b :: k) c
+ Data.Tax.ATO: data ABN
+ Data.Tax.ATO: division293Income :: forall a (y :: Nat). RealFrac a => TaxReturnInfo y a -> Money a
+ Data.Tax.ATO: essEmployerDetails :: forall a f. Functor f => (PayerDetails -> f PayerDetails) -> ESSStatement a -> f (ESSStatement a)
+ Data.Tax.ATO: foreignIncomeTaxOffsets :: forall a f. Functor f => (Money a -> f (Money a)) -> TaxAssessment a -> f (TaxAssessment a)
+ Data.Tax.ATO: frankingCreditOffset :: forall a f. Functor f => (Money a -> f (Money a)) -> TaxAssessment a -> f (TaxAssessment a)
+ Data.Tax.ATO: instance Data.Tax.ATO.CGT.HasCapitalLossCarryForward Data.Tax.ATO.TaxAssessment a
+ Data.Tax.ATO: instance Data.Tax.ATO.Common.HasTaxWithheld Data.Tax.ATO.ESSStatement a a
+ Data.Tax.ATO: instance Data.Tax.ATO.Common.HasTaxWithheld Data.Tax.ATO.GrossAndWithheld a a
+ Data.Tax.ATO: instance Data.Tax.ATO.Common.HasTaxWithheld Data.Tax.ATO.TaxAssessment a a
+ Data.Tax.ATO: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Tax.ATO.ESSStatement a)
+ Data.Tax.ATO: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.Tax.ATO.ESSStatement a)
+ Data.Tax.ATO: instance GHC.Num.Num a => Data.Tax.ATO.Common.HasTaxWithheld (Data.Tax.ATO.TaxReturnInfo y) a a
+ Data.Tax.ATO: instance GHC.Real.RealFrac a => Data.Tax.ATO.Common.HasTaxWithheld Data.Tax.ATO.Dividend a a
+ Data.Tax.ATO: medicareLevySurchargeDue :: forall a f. Functor f => (Money a -> f (Money a)) -> TaxAssessment a -> f (TaxAssessment a)
+ Data.Tax.ATO: offsetForSuperannuationContributionsOnBehalfOfYourSpouse :: forall a f. Functor f => (Money a -> f (Money a)) -> TaxAssessment a -> f (TaxAssessment a)
+ Data.Tax.ATO: paygInstalmentIncome :: forall a (y :: Nat). RealFrac a => TaxReturnInfo y a -> Money a
+ Data.Tax.ATO: paymentSummariesBusinessAndPersonalServicesIncome :: forall (y :: Nat) a f. Functor f => ([PaymentSummaryBusinessAndPersonalServicesIncome a] -> f [PaymentSummaryBusinessAndPersonalServicesIncome a]) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
+ Data.Tax.ATO: paymentSummariesForeignEmployment :: forall (y :: Nat) a f. Functor f => ([PaymentSummaryForeignEmployment a] -> f [PaymentSummaryForeignEmployment a]) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
+ Data.Tax.ATO: paymentSummariesIndividualNonBusiness :: forall (y :: Nat) a f. Functor f => ([PaymentSummaryIndividualNonBusiness a] -> f [PaymentSummaryIndividualNonBusiness a]) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
+ Data.Tax.ATO: paymentSummariesWithholdingWhereABNNotQuoted :: forall (y :: Nat) a f. Functor f => ([PaymentSummaryWithholdingWhereABNNotQuoted a] -> f [PaymentSummaryWithholdingWhereABNNotQuoted a]) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
+ Data.Tax.ATO.ABN: asInt :: ABN -> Int
+ Data.Tax.ATO.ABN: asString :: ABN -> String
+ Data.Tax.ATO.ABN: data ABN
+ Data.Tax.ATO.ABN: fromInt :: Int -> Maybe ABN
+ Data.Tax.ATO.ABN: instance Data.String.IsString Data.Tax.ATO.ABN.ABN
+ Data.Tax.ATO.ABN: instance GHC.Classes.Eq Data.Tax.ATO.ABN.ABN
+ Data.Tax.ATO.ABN: instance GHC.Classes.Ord Data.Tax.ATO.ABN.ABN
+ Data.Tax.ATO.ABN: instance GHC.Show.Show Data.Tax.ATO.ABN.ABN
+ Data.Tax.ATO.ABN: parse :: String -> Maybe ABN
+ Data.Tax.ATO.CGT: cgtNetLossesCarriedForward :: forall a f. Functor f => (Money a -> f (Money a)) -> CGTAssessment a -> f (CGTAssessment a)
+ Data.Tax.ATO.CGT: cgtTotalCurrentYearGains :: forall a f. Functor f => (Money a -> f (Money a)) -> CGTAssessment a -> f (CGTAssessment a)
+ Data.Tax.ATO.CGT: instance Data.Tax.ATO.CGT.HasCapitalLossCarryForward Data.Tax.ATO.CGT.CGTAssessment a
+ Data.Tax.ATO.CGT: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Tax.ATO.CGT.CGTAssessment a)
+ Data.Tax.ATO.CGT: nullCGTAssessment :: Num a => CGTAssessment a
+ Data.Tax.ATO.Common: MedicareLevyRatesAndThresholds :: a -> Money a -> Money a -> Money a -> Money a -> Money a -> MedicareLevyRatesAndThresholds a
+ Data.Tax.ATO.Common: [medicareLevyRate] :: MedicareLevyRatesAndThresholds a -> a
+ Data.Tax.ATO.Common: [medicareLevyThresholdDependentChildIncrease] :: MedicareLevyRatesAndThresholds a -> Money a
+ Data.Tax.ATO.Common: [medicareLevyThresholdFamilySeniorAndPensioner] :: MedicareLevyRatesAndThresholds a -> Money a
+ Data.Tax.ATO.Common: [medicareLevyThresholdFamily] :: MedicareLevyRatesAndThresholds a -> Money a
+ Data.Tax.ATO.Common: [medicareLevyThresholdIndividualSeniorAndPensioner] :: MedicareLevyRatesAndThresholds a -> Money a
+ Data.Tax.ATO.Common: [medicareLevyThresholdIndividual] :: MedicareLevyRatesAndThresholds a -> Money a
+ Data.Tax.ATO.Common: [ttMedicareLevyRatesAndThresholds] :: TaxTables (y :: k) a -> MedicareLevyRatesAndThresholds a
+ Data.Tax.ATO.Common: applyCentsPerKilometreMethod :: forall {k} (y :: k) a. (HasCentsPerKilometreMethod y, Fractional a, Ord a) => a -> Money a
+ Data.Tax.ATO.Common: applyFixedRateMethod :: forall {k} (y :: k) a. (HasFixedRateMethod y, Fractional a) => a -> Money a
+ Data.Tax.ATO.Common: applyFixedRateMethodPre2023 :: forall {k} (y :: k) a. (HasFixedRateMethodPre2023 y, Fractional a) => a -> Money a
+ Data.Tax.ATO.Common: applyShortcutMethod :: forall {k} (y :: k) a. (HasShortcutMethod y, Fractional a) => a -> Money a
+ Data.Tax.ATO.Common: class HasCentsPerKilometreMethod (y :: k)
+ Data.Tax.ATO.Common: class HasFixedRateMethod (y :: k)
+ Data.Tax.ATO.Common: class HasFixedRateMethodPre2023 (y :: k)
+ Data.Tax.ATO.Common: class HasShortcutMethod (y :: k)
+ Data.Tax.ATO.Common: class HasTaxWithheld (a :: k -> Type) (b :: k) c
+ Data.Tax.ATO.Common: data MedicareLevyRatesAndThresholds a
+ Data.Tax.ATO.Common: instance (2002 Data.Type.Ord.<= y, y Data.Type.Ord.<= 2022, Data.Tax.ATO.FY.FinancialYear y) => Data.Tax.ATO.Common.HasFixedRateMethodPre2023 y
+ Data.Tax.ATO.Common: instance (2016 Data.Type.Ord.<= y, y Data.Type.Ord.<= 2025, Data.Tax.ATO.FY.FinancialYear y) => Data.Tax.ATO.Common.HasCentsPerKilometreMethod y
+ Data.Tax.ATO.Common: instance (2020 Data.Type.Ord.<= y, y Data.Type.Ord.<= 2022) => Data.Tax.ATO.Common.HasShortcutMethod y
+ Data.Tax.ATO.Common: instance (Data.Foldable.Foldable t, Data.Tax.ATO.Common.HasTaxWithheld x a a, GHC.Num.Num a) => Data.Tax.ATO.Common.HasTaxWithheld t (x a) a
+ Data.Tax.ATO.Common: instance Data.Tax.ATO.Common.HasFixedRateMethod 2023
+ Data.Tax.ATO.Common: instance Data.Tax.ATO.Common.HasFixedRateMethod 2024
+ Data.Tax.ATO.Common: instance Data.Tax.ATO.Common.HasFixedRateMethod 2025
+ Data.Tax.ATO.Common: medicareLevy' :: (Fractional a, Ord a) => MedicareLevyRatesAndThresholds a -> Money a -> Maybe (Money a) -> Integer -> Money a
+ Data.Tax.ATO.Common: taxWithheld :: HasTaxWithheld a b c => Getter (a b) (Money c)
+ Data.Tax.ATO.Depreciation: DepreciatingAsset :: Day -> Money a -> EffectiveLife -> DepreciationMethod a -> DepreciatingAsset a
+ Data.Tax.ATO.Depreciation: data DepreciatingAsset a
+ Data.Tax.ATO.Depreciation: declineInValue :: forall (y :: Nat) a. (FinancialYear y, Fractional a, Ord a) => Proxy y -> DepreciatingAsset a -> Money a
+ Data.Tax.ATO.Depreciation: depreciationSchedule :: (Fractional a, Ord a) => DepreciatingAsset a -> [(Year, Money a)]
+ Data.Tax.ATO.Depreciation: diminishingValueMethod :: Fractional a => DepreciationMethod a
+ Data.Tax.ATO.Depreciation: primeCostMethod :: Fractional a => DepreciationMethod a
+ Data.Tax.ATO.Depreciation: type DepreciationMethod a = Day -> EffectiveLife -> (Money a, Money a) -> Money a
+ Data.Tax.ATO.Depreciation: type EffectiveLife = Rational
+ Data.Tax.ATO.FY: daysInYear :: Year -> Integer
+ Data.Tax.ATO.FY: daysInYearFromProxy :: forall (y :: Nat). FinancialYear y => Proxy y -> Integer
+ Data.Tax.ATO.FY: fromProxy :: forall (y :: Nat). FinancialYear y => Proxy y -> Year
+ Data.Tax.ATO.FY.FY2017: fyProxy :: Proxy FY
+ Data.Tax.ATO.FY.FY2017: type FY = 2017
+ Data.Tax.ATO.FY.FY2025: fyProxy :: Proxy FY
+ Data.Tax.ATO.FY.FY2025: tables :: (Ord a, Fractional a) => TaxTables FY a
+ Data.Tax.ATO.FY.FY2025: type FY = 2025
+ Data.Tax.ATO.PaymentSummary: EmployerFBTExempt :: FBTEmployerExemption
+ Data.Tax.ATO.PaymentSummary: EmployerNotFBTExempt :: FBTEmployerExemption
+ Data.Tax.ATO.PaymentSummary: GrossPaymentsTypeF :: GrossPaymentsTypeForeignEmployment
+ Data.Tax.ATO.PaymentSummary: GrossPaymentsTypeH :: GrossPaymentsTypeIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: GrossPaymentsTypeJ :: GrossPaymentsTypeForeignEmployment
+ Data.Tax.ATO.PaymentSummary: GrossPaymentsTypeP :: GrossPaymentsTypeIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: LumpSumATypeR :: LumpSumAType
+ Data.Tax.ATO.PaymentSummary: LumpSumATypeT :: LumpSumAType
+ Data.Tax.ATO.PaymentSummary: ReportableFringeBenefits :: Money a -> FBTEmployerExemption -> ReportableFringeBenefits a
+ Data.Tax.ATO.PaymentSummary: allowance :: RealFrac a => String -> Money a -> Allowance a
+ Data.Tax.ATO.PaymentSummary: allowanceAmount :: forall a b f. Functor f => (Money a -> f (Money b)) -> Allowance a -> f (Allowance b)
+ Data.Tax.ATO.PaymentSummary: allowanceDetail :: forall a f. Functor f => (String -> f String) -> Allowance a -> f (Allowance a)
+ Data.Tax.ATO.PaymentSummary: allowances :: forall a f. Functor f => ([Allowance a] -> f [Allowance a]) -> PaymentSummaryIndividualNonBusiness a -> f (PaymentSummaryIndividualNonBusiness a)
+ Data.Tax.ATO.PaymentSummary: class HasGrossPayments (s :: Type -> Type)
+ Data.Tax.ATO.PaymentSummary: class HasGrossPaymentsType (s :: k -> Type) a
+ Data.Tax.ATO.PaymentSummary: class HasLumpSumA (s :: Type -> Type)
+ Data.Tax.ATO.PaymentSummary: class HasLumpSumD (s :: Type -> Type)
+ Data.Tax.ATO.PaymentSummary: class HasLumpSumE (s :: Type -> Type)
+ Data.Tax.ATO.PaymentSummary: class HasPayerDetails (s :: k -> Type)
+ Data.Tax.ATO.PaymentSummary: class HasReportableEmployerSuperannuationContributions (s :: Type -> Type)
+ Data.Tax.ATO.PaymentSummary: class HasReportableFringeBenefits (s :: Type -> Type)
+ Data.Tax.ATO.PaymentSummary: class HasTotalTaxWithheld (s :: Type -> Type)
+ Data.Tax.ATO.PaymentSummary: data Allowance a
+ Data.Tax.ATO.PaymentSummary: data FBTEmployerExemption
+ Data.Tax.ATO.PaymentSummary: data GrossPaymentsTypeForeignEmployment
+ Data.Tax.ATO.PaymentSummary: data GrossPaymentsTypeIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: data LumpSumA a
+ Data.Tax.ATO.PaymentSummary: data LumpSumAType
+ Data.Tax.ATO.PaymentSummary: data PayerDetails
+ Data.Tax.ATO.PaymentSummary: data PaymentSummaryBusinessAndPersonalServicesIncome a
+ Data.Tax.ATO.PaymentSummary: data PaymentSummaryForeignEmployment a
+ Data.Tax.ATO.PaymentSummary: data PaymentSummaryIndividualNonBusiness a
+ Data.Tax.ATO.PaymentSummary: data PaymentSummaryWithholdingWhereABNNotQuoted a
+ Data.Tax.ATO.PaymentSummary: data ReportableFringeBenefits a
+ Data.Tax.ATO.PaymentSummary: exemptForeignEmploymentIncome :: forall a f. Functor f => (Money a -> f (Money a)) -> PaymentSummaryIndividualNonBusiness a -> f (PaymentSummaryIndividualNonBusiness a)
+ Data.Tax.ATO.PaymentSummary: foreignTaxPaid :: forall a f. Functor f => (Money a -> f (Money a)) -> PaymentSummaryForeignEmployment a -> f (PaymentSummaryForeignEmployment a)
+ Data.Tax.ATO.PaymentSummary: fringeBenefitsEmployerExempt :: Money a -> Maybe (ReportableFringeBenefits a)
+ Data.Tax.ATO.PaymentSummary: fringeBenefitsEmployerNotExempt :: Money a -> Maybe (ReportableFringeBenefits a)
+ Data.Tax.ATO.PaymentSummary: grossPayments :: HasGrossPayments s => Lens' (s a) (Money a)
+ Data.Tax.ATO.PaymentSummary: grossPaymentsType :: forall (any :: k). HasGrossPaymentsType s a => Lens' (s any) a
+ Data.Tax.ATO.PaymentSummary: grossPaymentsTypeH :: Maybe GrossPaymentsTypeIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: grossPaymentsTypeP :: Maybe GrossPaymentsTypeIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: instance Data.String.IsString Data.Tax.ATO.PaymentSummary.PayerDetails
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.Common.HasTaxWithheld Data.Tax.ATO.PaymentSummary.PaymentSummaryBusinessAndPersonalServicesIncome a a
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.Common.HasTaxWithheld Data.Tax.ATO.PaymentSummary.PaymentSummaryForeignEmployment a a
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.Common.HasTaxWithheld Data.Tax.ATO.PaymentSummary.PaymentSummaryIndividualNonBusiness a a
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.Common.HasTaxWithheld Data.Tax.ATO.PaymentSummary.PaymentSummaryWithholdingWhereABNNotQuoted a a
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.Common.HasTaxableIncome Data.Tax.ATO.PaymentSummary.PaymentSummaryBusinessAndPersonalServicesIncome a a
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.Common.HasTaxableIncome Data.Tax.ATO.PaymentSummary.PaymentSummaryWithholdingWhereABNNotQuoted a a
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasGrossPayments Data.Tax.ATO.PaymentSummary.PaymentSummaryBusinessAndPersonalServicesIncome
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasGrossPayments Data.Tax.ATO.PaymentSummary.PaymentSummaryForeignEmployment
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasGrossPayments Data.Tax.ATO.PaymentSummary.PaymentSummaryIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasGrossPayments Data.Tax.ATO.PaymentSummary.PaymentSummaryWithholdingWhereABNNotQuoted
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasGrossPaymentsType Data.Tax.ATO.PaymentSummary.PaymentSummaryForeignEmployment Data.Tax.ATO.PaymentSummary.GrossPaymentsTypeForeignEmployment
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasGrossPaymentsType Data.Tax.ATO.PaymentSummary.PaymentSummaryIndividualNonBusiness (GHC.Maybe.Maybe Data.Tax.ATO.PaymentSummary.GrossPaymentsTypeIndividualNonBusiness)
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasLumpSumA Data.Tax.ATO.PaymentSummary.PaymentSummaryForeignEmployment
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasLumpSumA Data.Tax.ATO.PaymentSummary.PaymentSummaryIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasLumpSumD Data.Tax.ATO.PaymentSummary.PaymentSummaryForeignEmployment
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasLumpSumD Data.Tax.ATO.PaymentSummary.PaymentSummaryIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasLumpSumE Data.Tax.ATO.PaymentSummary.PaymentSummaryForeignEmployment
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasLumpSumE Data.Tax.ATO.PaymentSummary.PaymentSummaryIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasPayerDetails Data.Tax.ATO.PaymentSummary.PaymentSummaryBusinessAndPersonalServicesIncome
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasPayerDetails Data.Tax.ATO.PaymentSummary.PaymentSummaryForeignEmployment
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasPayerDetails Data.Tax.ATO.PaymentSummary.PaymentSummaryIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasPayerDetails Data.Tax.ATO.PaymentSummary.PaymentSummaryWithholdingWhereABNNotQuoted
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasReportableEmployerSuperannuationContributions Data.Tax.ATO.PaymentSummary.PaymentSummaryBusinessAndPersonalServicesIncome
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasReportableEmployerSuperannuationContributions Data.Tax.ATO.PaymentSummary.PaymentSummaryForeignEmployment
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasReportableEmployerSuperannuationContributions Data.Tax.ATO.PaymentSummary.PaymentSummaryIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasReportableFringeBenefits Data.Tax.ATO.PaymentSummary.PaymentSummaryForeignEmployment
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasReportableFringeBenefits Data.Tax.ATO.PaymentSummary.PaymentSummaryIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasTotalTaxWithheld Data.Tax.ATO.PaymentSummary.PaymentSummaryBusinessAndPersonalServicesIncome
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasTotalTaxWithheld Data.Tax.ATO.PaymentSummary.PaymentSummaryForeignEmployment
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasTotalTaxWithheld Data.Tax.ATO.PaymentSummary.PaymentSummaryIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: instance Data.Tax.ATO.PaymentSummary.HasTotalTaxWithheld Data.Tax.ATO.PaymentSummary.PaymentSummaryWithholdingWhereABNNotQuoted
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Eq Data.Tax.ATO.PaymentSummary.FBTEmployerExemption
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Eq Data.Tax.ATO.PaymentSummary.GrossPaymentsTypeForeignEmployment
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Eq Data.Tax.ATO.PaymentSummary.GrossPaymentsTypeIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Eq Data.Tax.ATO.PaymentSummary.LumpSumAType
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Eq Data.Tax.ATO.PaymentSummary.PayerDetails
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Tax.ATO.PaymentSummary.Allowance a)
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Tax.ATO.PaymentSummary.LumpSumA a)
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Tax.ATO.PaymentSummary.ReportableFringeBenefits a)
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Ord Data.Tax.ATO.PaymentSummary.FBTEmployerExemption
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Ord Data.Tax.ATO.PaymentSummary.GrossPaymentsTypeForeignEmployment
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Ord Data.Tax.ATO.PaymentSummary.GrossPaymentsTypeIndividualNonBusiness
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Ord Data.Tax.ATO.PaymentSummary.LumpSumAType
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Ord Data.Tax.ATO.PaymentSummary.PayerDetails
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.Tax.ATO.PaymentSummary.Allowance a)
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.Tax.ATO.PaymentSummary.LumpSumA a)
+ Data.Tax.ATO.PaymentSummary: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.Tax.ATO.PaymentSummary.ReportableFringeBenefits a)
+ Data.Tax.ATO.PaymentSummary: instance GHC.Real.RealFrac a => Data.Tax.ATO.Common.HasTaxableIncome Data.Tax.ATO.PaymentSummary.PaymentSummaryForeignEmployment a a
+ Data.Tax.ATO.PaymentSummary: instance GHC.Real.RealFrac a => Data.Tax.ATO.Common.HasTaxableIncome Data.Tax.ATO.PaymentSummary.PaymentSummaryIndividualNonBusiness a a
+ Data.Tax.ATO.PaymentSummary: lumpSumA :: HasLumpSumA s => Lens' (s a) (Maybe (LumpSumA a))
+ Data.Tax.ATO.PaymentSummary: lumpSumAAmount :: forall a b f. Functor f => (Money a -> f (Money b)) -> LumpSumA a -> f (LumpSumA b)
+ Data.Tax.ATO.PaymentSummary: lumpSumAType :: forall a f. Functor f => (LumpSumAType -> f LumpSumAType) -> LumpSumA a -> f (LumpSumA a)
+ Data.Tax.ATO.PaymentSummary: lumpSumATypeR :: RealFrac a => Money a -> LumpSumA a
+ Data.Tax.ATO.PaymentSummary: lumpSumATypeT :: RealFrac a => Money a -> LumpSumA a
+ Data.Tax.ATO.PaymentSummary: lumpSumB :: forall a f. Functor f => (Money a -> f (Money a)) -> PaymentSummaryIndividualNonBusiness a -> f (PaymentSummaryIndividualNonBusiness a)
+ Data.Tax.ATO.PaymentSummary: lumpSumD :: HasLumpSumD s => Lens' (s a) (Money a)
+ Data.Tax.ATO.PaymentSummary: lumpSumE :: HasLumpSumE s => Lens' (s a) (Money a)
+ Data.Tax.ATO.PaymentSummary: newPayerDetails :: ABN -> Maybe Int -> String -> PayerDetails
+ Data.Tax.ATO.PaymentSummary: newPaymentSummaryBusinessAndPersonalServicesIncome :: Num a => PayerDetails -> PaymentSummaryBusinessAndPersonalServicesIncome a
+ Data.Tax.ATO.PaymentSummary: newPaymentSummaryForeignEmployment :: Num a => PayerDetails -> PaymentSummaryForeignEmployment a
+ Data.Tax.ATO.PaymentSummary: newPaymentSummaryIndividualNonBusiness :: Num a => PayerDetails -> PaymentSummaryIndividualNonBusiness a
+ Data.Tax.ATO.PaymentSummary: newPaymentSummaryWithholdingWhereABNNotQuoted :: Num a => PayerDetails -> PaymentSummaryWithholdingWhereABNNotQuoted a
+ Data.Tax.ATO.PaymentSummary: pattern PaymentSummary :: Num a => PayerDetails -> Money a -> Money a -> Money a -> PaymentSummaryIndividualNonBusiness a
+ Data.Tax.ATO.PaymentSummary: payerABN :: Lens' PayerDetails ABN
+ Data.Tax.ATO.PaymentSummary: payerBranchNumber :: Lens' PayerDetails (Maybe Int)
+ Data.Tax.ATO.PaymentSummary: payerDetails :: forall (a :: k). HasPayerDetails s => Lens' (s a) PayerDetails
+ Data.Tax.ATO.PaymentSummary: payerName :: Lens' PayerDetails String
+ Data.Tax.ATO.PaymentSummary: reportableEmployerSuperannuationContributions :: HasReportableEmployerSuperannuationContributions s => Lens' (s a) (Money a)
+ Data.Tax.ATO.PaymentSummary: reportableFringeBenefits :: HasReportableFringeBenefits s => Lens' (s a) (Maybe (ReportableFringeBenefits a))
+ Data.Tax.ATO.PaymentSummary: totalTaxWithheld :: HasTotalTaxWithheld s => Lens' (s a) (Money a)
+ Data.Tax.ATO.Pretty: formatMoney :: Money Rational -> Doc
+ Data.Tax.ATO.TFN: asInt :: TFN -> Int
+ Data.Tax.ATO.TFN: asString :: TFN -> String
+ Data.Tax.ATO.TFN: data TFN
+ Data.Tax.ATO.TFN: fromInt :: Int -> Maybe TFN
+ Data.Tax.ATO.TFN: instance Data.String.IsString Data.Tax.ATO.TFN.TFN
+ Data.Tax.ATO.TFN: instance GHC.Classes.Eq Data.Tax.ATO.TFN.TFN
+ Data.Tax.ATO.TFN: instance GHC.Classes.Ord Data.Tax.ATO.TFN.TFN
+ Data.Tax.ATO.TFN: instance GHC.Show.Show Data.Tax.ATO.TFN.TFN
+ Data.Tax.ATO.TFN: parse :: String -> Maybe TFN
- Data.Tax.ATO: assessTax :: (FinancialYear y, RealFrac a) => TaxTables y a -> TaxReturnInfo y a -> TaxAssessment a
+ Data.Tax.ATO: assessTax :: forall (y :: Nat) a. (FinancialYear y, RealFrac a) => TaxTables y a -> TaxReturnInfo y a -> TaxAssessment a
- Data.Tax.ATO: cgtEvents :: Lens' (TaxReturnInfo y a) [CGTEvent a]
+ Data.Tax.ATO: cgtEvents :: forall (y :: Nat) a f. Functor f => ([CGTEvent a] -> f [CGTEvent a]) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: childSupportPaid :: Lens' (IncomeTests a) (Money a)
+ Data.Tax.ATO: childSupportPaid :: forall a f. Functor f => (Money a -> f (Money a)) -> IncomeTests a -> f (IncomeTests a)
- Data.Tax.ATO: class HasCapitalLossCarryForward a b
+ Data.Tax.ATO: class HasCapitalLossCarryForward (a :: Type -> Type) b
- Data.Tax.ATO: class HasTaxWithheld a b c
+ Data.Tax.ATO: class HasTaxWithheld (a :: k -> Type) (b :: k) c
- Data.Tax.ATO: costOfManagingTaxAffairs :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: costOfManagingTaxAffairs :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: data TaxReturnInfo y a
+ Data.Tax.ATO: data TaxReturnInfo (y :: Nat) a
- Data.Tax.ATO: deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: deductibleAmountOfUndeductedPurchasePriceOfAForeignPensionOrAnnuity :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: deductionForProjectPool :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: deductionForProjectPool :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: deductions :: Lens' (TaxReturnInfo y a) (Deductions a)
+ Data.Tax.ATO: deductions :: forall (y :: Nat) a f. Functor f => (Deductions a -> f (Deductions a)) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: dependentChildren :: Lens' (IncomeTests a) Integer
+ Data.Tax.ATO: dependentChildren :: forall a f. Functor f => (Integer -> f Integer) -> IncomeTests a -> f (IncomeTests a)
- Data.Tax.ATO: dividendDeductions :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: dividendDeductions :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: dividends :: Lens' (TaxReturnInfo y a) [Dividend a]
+ Data.Tax.ATO: dividends :: forall (y :: Nat) a f. Functor f => ([Dividend a] -> f [Dividend a]) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: ess :: Lens' (TaxReturnInfo y a) (ESSStatement a)
+ Data.Tax.ATO: ess :: forall (y :: Nat) a f. Functor f => ([ESSStatement a] -> f [ESSStatement a]) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: essDeferral :: Lens' (ESSStatement a) (Money a)
+ Data.Tax.ATO: essDeferral :: forall a f. Functor f => (Money a -> f (Money a)) -> ESSStatement a -> f (ESSStatement a)
- Data.Tax.ATO: essForeignSourceDiscounts :: Lens' (ESSStatement a) (Money a)
+ Data.Tax.ATO: essForeignSourceDiscounts :: forall a f. Functor f => (Money a -> f (Money a)) -> ESSStatement a -> f (ESSStatement a)
- Data.Tax.ATO: essPre2009 :: Lens' (ESSStatement a) (Money a)
+ Data.Tax.ATO: essPre2009 :: forall a f. Functor f => (Money a -> f (Money a)) -> ESSStatement a -> f (ESSStatement a)
- Data.Tax.ATO: essTFNAmounts :: Lens' (ESSStatement a) (Money a)
+ Data.Tax.ATO: essTFNAmounts :: forall a f. Functor f => (Money a -> f (Money a)) -> ESSStatement a -> f (ESSStatement a)
- Data.Tax.ATO: essTaxedUpfrontNoReduction :: Lens' (ESSStatement a) (Money a)
+ Data.Tax.ATO: essTaxedUpfrontNoReduction :: forall a f. Functor f => (Money a -> f (Money a)) -> ESSStatement a -> f (ESSStatement a)
- Data.Tax.ATO: essTaxedUpfrontReduction :: Lens' (ESSStatement a) (Money a)
+ Data.Tax.ATO: essTaxedUpfrontReduction :: forall a f. Functor f => (Money a -> f (Money a)) -> ESSStatement a -> f (ESSStatement a)
- Data.Tax.ATO: foreignIncome :: Lens' (TaxReturnInfo y a) (Money a)
+ Data.Tax.ATO: foreignIncome :: forall (y :: Nat) a f. Functor f => (Money a -> f (Money a)) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: foreignIncomeDeductions :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: foreignIncomeDeductions :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: foreignTaxOffset :: Lens' (Offsets a) (Money a)
+ Data.Tax.ATO: foreignTaxOffset :: forall a f. Functor f => (Money a -> f (Money a)) -> Offsets a -> f (Offsets a)
- Data.Tax.ATO: forestryManagedInvestmentSchemeDeduction :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: forestryManagedInvestmentSchemeDeduction :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: giftsOrDonations :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: giftsOrDonations :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: helpBalance :: Lens' (TaxReturnInfo y a) (Money a)
+ Data.Tax.ATO: helpBalance :: forall (y :: Nat) a f. Functor f => (Money a -> f (Money a)) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: incomeTests :: Lens' (TaxReturnInfo y a) (IncomeTests a)
+ Data.Tax.ATO: incomeTests :: forall (y :: Nat) a f. Functor f => (IncomeTests a -> f (IncomeTests a)) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: interest :: Lens' (TaxReturnInfo y a) (GrossAndWithheld a)
+ Data.Tax.ATO: interest :: forall (y :: Nat) a f. Functor f => (GrossAndWithheld a -> f (GrossAndWithheld a)) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: interestDeductions :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: interestDeductions :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: lowValuePoolDeduction :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: lowValuePoolDeduction :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: medicareLevyDue :: Getter (TaxAssessment a) (Money a)
+ Data.Tax.ATO: medicareLevyDue :: forall a f. Functor f => (Money a -> f (Money a)) -> TaxAssessment a -> f (TaxAssessment a)
- Data.Tax.ATO: mlsExemption :: Lens' (TaxReturnInfo y a) (Days y)
+ Data.Tax.ATO: mlsExemption :: forall (y :: Nat) a f. Functor f => (Days y -> f (Days y)) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: newESSStatement :: Num a => ESSStatement a
+ Data.Tax.ATO: newESSStatement :: Num a => PayerDetails -> ESSStatement a
- Data.Tax.ATO: newTaxReturnInfo :: (FinancialYear y, Num a) => TaxReturnInfo y a
+ Data.Tax.ATO: newTaxReturnInfo :: forall (y :: Nat) a. (FinancialYear y, Num a) => TaxReturnInfo y a
- Data.Tax.ATO: newTaxReturnInfoForTables :: (FinancialYear y, Num a) => TaxTables y a -> TaxReturnInfo y a
+ Data.Tax.ATO: newTaxReturnInfoForTables :: forall (y :: Nat) a. (FinancialYear y, Num a) => TaxTables y a -> TaxReturnInfo y a
- Data.Tax.ATO: offsets :: Lens' (TaxReturnInfo y a) (Offsets a)
+ Data.Tax.ATO: offsets :: forall (y :: Nat) a f. Functor f => (Offsets a -> f (Offsets a)) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: otherDeductions :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: otherDeductions :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: otherWorkRelatedExpenses :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: otherWorkRelatedExpenses :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: paygInstalments :: Lens' (Offsets a) (Money a)
+ Data.Tax.ATO: paygInstalments :: forall a f. Functor f => (Money a -> f (Money a)) -> Offsets a -> f (Offsets a)
- Data.Tax.ATO: paygInstalmentsCredit :: Lens' (TaxAssessment a) (Money a)
+ Data.Tax.ATO: paygInstalmentsCredit :: forall a f. Functor f => (Money a -> f (Money a)) -> TaxAssessment a -> f (TaxAssessment a)
- Data.Tax.ATO: paymentSummaries :: Lens' (TaxReturnInfo y a) [PaymentSummary a]
+ Data.Tax.ATO: paymentSummaries :: forall (y :: Nat) a f. Functor f => ([PaymentSummaryIndividualNonBusiness a] -> f [PaymentSummaryIndividualNonBusiness a]) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: personalSuperannuationContributions :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: personalSuperannuationContributions :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: privateHealthInsurancePolicyDetails :: Lens' (TaxReturnInfo y a) [PrivateHealthInsurancePolicyDetail a]
+ Data.Tax.ATO: privateHealthInsurancePolicyDetails :: forall (y :: Nat) a f. Functor f => ([PrivateHealthInsurancePolicyDetail a] -> f [PrivateHealthInsurancePolicyDetail a]) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: privateHealthInsuranceRebateAdjustment :: Lens' (TaxAssessment a) (Money a)
+ Data.Tax.ATO: privateHealthInsuranceRebateAdjustment :: forall a f. Functor f => (Money a -> f (Money a)) -> TaxAssessment a -> f (TaxAssessment a)
- Data.Tax.ATO: sfssBalance :: Lens' (TaxReturnInfo y a) (Money a)
+ Data.Tax.ATO: sfssBalance :: forall (y :: Nat) a f. Functor f => (Money a -> f (Money a)) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: spouseContributionOffset :: Lens' (Offsets a) (Money a)
+ Data.Tax.ATO: spouseContributionOffset :: forall a f. Functor f => (Money a -> f (Money a)) -> Offsets a -> f (Offsets a)
- Data.Tax.ATO: spouseDetails :: Lens' (TaxReturnInfo y a) (Maybe (SpouseDetails a))
+ Data.Tax.ATO: spouseDetails :: forall (y :: Nat) a f. Functor f => (Maybe (SpouseDetails a) -> f (Maybe (SpouseDetails a))) -> TaxReturnInfo y a -> f (TaxReturnInfo y a)
- Data.Tax.ATO: spouseTaxableIncome :: Lens' (SpouseDetails a) (Money a)
+ Data.Tax.ATO: spouseTaxableIncome :: forall a f. Functor f => (Money a -> f (Money a)) -> SpouseDetails a -> f (SpouseDetails a)
- Data.Tax.ATO: studyAndTrainingLoanRepayment :: Lens' (TaxAssessment a) (Money a)
+ Data.Tax.ATO: studyAndTrainingLoanRepayment :: forall a f. Functor f => (Money a -> f (Money a)) -> TaxAssessment a -> f (TaxAssessment a)
- Data.Tax.ATO: targetForeignIncome :: Lens' (IncomeTests a) (Money a)
+ Data.Tax.ATO: targetForeignIncome :: forall a f. Functor f => (Money a -> f (Money a)) -> IncomeTests a -> f (IncomeTests a)
- Data.Tax.ATO: taxBalance :: Num a => Getter (TaxAssessment a) (Money a)
+ Data.Tax.ATO: taxBalance :: (Num a, Ord a) => Getter (TaxAssessment a) (Money a)
- Data.Tax.ATO: taxCGTAssessment :: Lens' (TaxAssessment a) (CGTAssessment a)
+ Data.Tax.ATO: taxCGTAssessment :: forall a f. Functor f => (CGTAssessment a -> f (CGTAssessment a)) -> TaxAssessment a -> f (TaxAssessment a)
- Data.Tax.ATO: taxDue :: Getter (TaxAssessment a) (Money a)
+ Data.Tax.ATO: taxDue :: forall a f. Functor f => (Money a -> f (Money a)) -> TaxAssessment a -> f (TaxAssessment a)
- Data.Tax.ATO: taxFreeGovernmentPensionsOrBenefits :: Lens' (IncomeTests a) (Money a)
+ Data.Tax.ATO: taxFreeGovernmentPensionsOrBenefits :: forall a f. Functor f => (Money a -> f (Money a)) -> IncomeTests a -> f (IncomeTests a)
- Data.Tax.ATO: workRelatedCarExpenses :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: workRelatedCarExpenses :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: workRelatedClothingLaundryAndDryCleaningExpenses :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: workRelatedClothingLaundryAndDryCleaningExpenses :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: workRelatedSelfEducationExpenses :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: workRelatedSelfEducationExpenses :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO: workRelatedTravelExpenses :: Lens' (Deductions a) (Money a)
+ Data.Tax.ATO: workRelatedTravelExpenses :: forall a f. Functor f => (Money a -> f (Money a)) -> Deductions a -> f (Deductions a)
- Data.Tax.ATO.CGT: cgtNetGain :: Num a => Getter (CGTAssessment a) (Money a)
+ Data.Tax.ATO.CGT: cgtNetGain :: forall a f. Functor f => (Money a -> f (Money a)) -> CGTAssessment a -> f (CGTAssessment a)
- Data.Tax.ATO.CGT: class HasCapitalGain a b c
+ Data.Tax.ATO.CGT: class HasCapitalGain (a :: k -> Type) (b :: k) c
- Data.Tax.ATO.CGT: class HasCapitalLossCarryForward a b
+ Data.Tax.ATO.CGT: class HasCapitalLossCarryForward (a :: Type -> Type) b
- Data.Tax.ATO.Common: TaxTables :: Tax (Money a) (Money a) -> Tax (Money a) (Money a) -> Tax (Money a) (Money a) -> Tax (Money a) (Money a) -> Tax (Money a) (Money a) -> Tax (Money a) (Money a) -> PrivateHealthInsuranceRebateRates a -> TaxTables y a
+ Data.Tax.ATO.Common: TaxTables :: Tax (Money a) (Money a) -> MedicareLevyRatesAndThresholds a -> Tax (Money a) (Money a) -> Tax (Money a) (Money a) -> Tax (Money a) (Money a) -> Tax (Money a) (Money a) -> PrivateHealthInsuranceRebateRates a -> TaxTables (y :: k) a
- Data.Tax.ATO.Common: [ttAdditional] :: TaxTables y a -> Tax (Money a) (Money a)
+ Data.Tax.ATO.Common: [ttAdditional] :: TaxTables (y :: k) a -> Tax (Money a) (Money a)
- Data.Tax.ATO.Common: [ttHelp] :: TaxTables y a -> Tax (Money a) (Money a)
+ Data.Tax.ATO.Common: [ttHelp] :: TaxTables (y :: k) a -> Tax (Money a) (Money a)
- Data.Tax.ATO.Common: [ttIndividualIncomeTax] :: TaxTables y a -> Tax (Money a) (Money a)
+ Data.Tax.ATO.Common: [ttIndividualIncomeTax] :: TaxTables (y :: k) a -> Tax (Money a) (Money a)
- Data.Tax.ATO.Common: [ttMedicareLevySurcharge] :: TaxTables y a -> Tax (Money a) (Money a)
+ Data.Tax.ATO.Common: [ttMedicareLevySurcharge] :: TaxTables (y :: k) a -> Tax (Money a) (Money a)
- Data.Tax.ATO.Common: [ttPHIRebateRates] :: TaxTables y a -> PrivateHealthInsuranceRebateRates a
+ Data.Tax.ATO.Common: [ttPHIRebateRates] :: TaxTables (y :: k) a -> PrivateHealthInsuranceRebateRates a
- Data.Tax.ATO.Common: [ttSfss] :: TaxTables y a -> Tax (Money a) (Money a)
+ Data.Tax.ATO.Common: [ttSfss] :: TaxTables (y :: k) a -> Tax (Money a) (Money a)
- Data.Tax.ATO.Common: class HasTaxableIncome a b c
+ Data.Tax.ATO.Common: class HasTaxableIncome (a :: k -> Type) (b :: k) c
- Data.Tax.ATO.Common: data TaxTables y a
+ Data.Tax.ATO.Common: data TaxTables (y :: k) a
- Data.Tax.ATO.FY: days :: forall a. FinancialYear a => Integer -> Days a
+ Data.Tax.ATO.FY: days :: forall (a :: Nat). FinancialYear a => Integer -> Days a
- Data.Tax.ATO.FY: daysAll :: forall a. FinancialYear a => Days a
+ Data.Tax.ATO.FY: daysAll :: forall (a :: Nat). FinancialYear a => Days a
- Data.Tax.ATO.FY: daysNone :: Days a
+ Data.Tax.ATO.FY: daysNone :: forall (a :: Nat). Days a
- Data.Tax.ATO.FY: financialYearRangeFromProxy :: forall n. FinancialYear n => Proxy n -> (Day, Day)
+ Data.Tax.ATO.FY: financialYearRangeFromProxy :: forall (n :: Nat). FinancialYear n => Proxy n -> (Day, Day)
- Data.Tax.ATO.FY: getFraction :: forall a frac. (FinancialYear a, Fractional frac) => Days a -> frac
+ Data.Tax.ATO.FY: getFraction :: forall (a :: Nat) frac. (FinancialYear a, Fractional frac) => Days a -> frac
- Data.Tax.ATO.Pretty: summariseTaxReturnInfo :: TaxReturnInfo y Rational -> Doc
+ Data.Tax.ATO.Pretty: summariseTaxReturnInfo :: forall (y :: Nat). TaxReturnInfo y Rational -> Doc
Files
- CHANGELOG.md +109/−0
- src/Data/Tax/ATO.hs +287/−148
- src/Data/Tax/ATO/ABN.hs +94/−0
- src/Data/Tax/ATO/CGT.hs +69/−68
- src/Data/Tax/ATO/Common.hs +218/−4
- src/Data/Tax/ATO/Depreciation.hs +87/−0
- src/Data/Tax/ATO/FY.hs +18/−10
- src/Data/Tax/ATO/FY/FY2017.hs +19/−4
- src/Data/Tax/ATO/FY/FY2018.hs +11/−2
- src/Data/Tax/ATO/FY/FY2019.hs +11/−2
- src/Data/Tax/ATO/FY/FY2020.hs +11/−2
- src/Data/Tax/ATO/FY/FY2021.hs +11/−2
- src/Data/Tax/ATO/FY/FY2022.hs +15/−6
- src/Data/Tax/ATO/FY/FY2023.hs +11/−2
- src/Data/Tax/ATO/FY/FY2024.hs +24/−6
- src/Data/Tax/ATO/FY/FY2025.hs +102/−0
- src/Data/Tax/ATO/PaymentSummary.hs +646/−0
- src/Data/Tax/ATO/Pretty.hs +74/−31
- src/Data/Tax/ATO/PrivateHealthInsuranceRebate.hs +0/−2
- src/Data/Tax/ATO/TFN.hs +94/−0
- tax-ato.cabal +16/−17
CHANGELOG.md view
@@ -1,3 +1,112 @@+## Version 2025.1++### Features and enhancements++- Overhauled payment summaries. More comprehensive data types and+ optics are provided in module `Data.Tax.ATO.PaymentSummary`.++ The old `PaymentSummary` constructor persists as a (deprecated)+ pattern synonym, for backwards compatibility. It will be removed+ in a future release.++- Implemented **reportable fringe benefits**. . Use the+ `fringeBenefitsEmployerNotExempt` or+ `fringeBenefitsEmployerExempt` constructors, along with the+ `reportableFringeBenefits` lens to add it to the payment summary.+ The amount is properly included in the surcharge and student loan+ repayment income calculations.++- Implemented **allowances**. A list of allowances can be added to+ a payment summary via the `allowances` lens. Construct allowance+ values with `allowance :: String -> Money a -> Allowance a`.++- Implemented **non-super lump sum A, B, D and E** payments.++- Implemented additional payment summary types:+ - Foreign Employment+ - Business and personal services income+ - Withholding where ABN not quoted++- New module `Data.Tax.ATO.Depreciation` provides types and+ functions for calculating decline in value (for deductions).+ Use the `DepreciatingAsset` data type to define depreciating+ assets, and the `declineInValue` function for calculating the+ decline in value in a given financial year.++- Added the "cents-per-kilometre" method for car expense deductions.+ Usage: `applyCentsPerKilometreMethod @FY kms`. ([#13])++- Added home office expense deduction methods ([#7]). Usage++ ```+ applyFixedRateMethod @FY hours+ applyShortcutMethod @FY hours+ applyFixedRateMethodPre2023 @FY hours+ ```++- Implement Medicare levy low income family thresholds, including+ increase based on number of dependents. Senior and pensioners+ individual and family thresholds remain unimplemented.++- CGT assessment types were overhauled and now contain more+ information about total capital gain and applied / unapplied+ losses. This is step toward a more complete CGT implementation.+ Remaining gaps include foreign withholding credits and separate+ treatment of collectables.++- Multiple ESS statements can now be added to a tax return. Also,+ the `essEmployeeDetails` field has been added, and+ `newESSStatement` was updated to take a `PayerDetails`. This is a+ breaking change. ([#16])++- Added `division293Income` which calculates the income component of+ Division 293 tax calculations. Some elements are not included+ because the relevant feature is not yet implemented (e.g. rental+ losses or FHSS releases). ([#12])++- Added `paygInstalmentIncome`, which calculates the PAYG instalment+ income. Some elements are not included because the relevant+ features are not yet implement (e.g. rent, partnership and trust+ income, PSI).++- Added the `Data.Tax.ATO.ABN` and `Data.Tax.ATO.TFN` modules, which+ have more representative data types, conversion functions, and+ proper validation. `IsString` instances are provided for+ compatibility with existing code.++- `TaxReturnInfo` pretty printing now includes more detailed ESS and+ CGT data, to help with preparation of tax returns.++- `TaxAssessment` pretty printing now separately reports Medicare+ levy, Medicare levy surcharge, and the various non-refundable and+ refundable tax offsets. The formatting closely resembles the ATO+ *notice of assessment* layout.++- Add `FY2025` module. All rates and thresholds are up to date.++- Added some new helper functions to the `Data.Tax.ATO.FY` module:+ - `fromProxy :: (FinancialYear y) => Proxy y -> Year`+ - `daysInYear :: Year -> Integer`+ - `daysInYearFromProxy :: FinancialYear y => Proxy y -> Integer`++### Bug fixes++- Non-refundable offsets now cannot reduce liability below $0, and+ the order of application of the various liabilities, offsets and+ credits has been fixed.++- Employee share scheme TFN amounts withheld are now included in+ assessment calculations ([#8]).++- Fix FY2024 private health insurance rebate tier thresholds.++[#7]: https://github.com/frasertweedale/hs-tax-ato/issues/7+[#8]: https://github.com/frasertweedale/hs-tax-ato/issues/8+[#12]: https://github.com/frasertweedale/hs-tax-ato/issues/12+[#13]: https://github.com/frasertweedale/hs-tax-ato/issues/13+[#16]: https://github.com/frasertweedale/hs-tax-ato/issues/16++ ## Version 2024.1 - The minimum supported version of GHC is now 9.2, due to a
src/Data/Tax/ATO.hs view
@@ -1,7 +1,5 @@-{-# LANGUAGE PolyKinds #-}- -- This file is part of hs-tax-ato--- Copyright (C) 2018-2021 Fraser Tweedale+-- Copyright (C) 2018-2025 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@@ -25,14 +23,11 @@ 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,+previous years, Medicare levy exemptions, adjustments, and variations based on family income and dependents. -} -{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}- module Data.Tax.ATO ( -- * Synopsis@@ -42,14 +37,15 @@ TaxReturnInfo , newTaxReturnInfo , newTaxReturnInfoForTables- , taxableIncome -- ** Income -- *** PAYG Payment Summaries- , PaymentSummary(..)+ , paymentSummariesIndividualNonBusiness+ , paymentSummariesForeignEmployment+ , paymentSummariesBusinessAndPersonalServicesIncome+ , paymentSummariesWithholdingWhereABNNotQuoted , paymentSummaries- , ABN -- *** Interest , interest@@ -70,6 +66,7 @@ , ESSStatement , newESSStatement , ess+ , essEmployerDetails , essTaxedUpfrontReduction , essTaxedUpfrontNoReduction , essDeferral@@ -124,6 +121,16 @@ , otherDeductions , foreignIncomeDeductions + -- *** Deduction methods+ , HasCentsPerKilometreMethod+ , applyCentsPerKilometreMethod+ , HasFixedRateMethod+ , applyFixedRateMethod+ , HasFixedRateMethodPre2023+ , applyFixedRateMethodPre2023+ , HasShortcutMethod+ , applyShortcutMethod+ -- ** Tax offsets , Offsets , offsets@@ -136,34 +143,50 @@ , assessTax , taxBalance , taxDue+ , offsetForSuperannuationContributionsOnBehalfOfYourSpouse+ , foreignIncomeTaxOffsets+ , frankingCreditOffset , medicareLevyDue+ , medicareLevySurchargeDue , studyAndTrainingLoanRepayment- , taxCreditsAndOffsets , paygInstalmentsCredit , taxCGTAssessment , privateHealthInsuranceRebateAdjustment + -- *** Division 293+ , division293Income++ -- *** PAYG instalments+ , paygInstalmentIncome+ -- * Corporate tax , corporateTax -- * Miscellaneous , GrossAndWithheld(..)+ , HasTaxableIncome(..) , HasTaxWithheld(..) , Proportion , getProportion , proportion , module Data.Tax+ , module Data.Tax.ATO.ABN+ , module Data.Tax.ATO.Depreciation+ , module Data.Tax.ATO.PaymentSummary , module Data.Tax.ATO.PrivateHealthInsuranceRebate , module Data.Tax.ATO.Rounding ) where -import Control.Lens (Getter, Lens', (&), foldOf, lens, set, to, view, views)+import Control.Lens (Getter, Lens', (&), foldOf, lens, preview, set, to, view, views) import Data.Time (Day) import Data.Tax import Data.Tax.ATO.CGT+import Data.Tax.ATO.ABN (ABN) import Data.Tax.ATO.Common+import Data.Tax.ATO.Depreciation import Data.Tax.ATO.FY+import Data.Tax.ATO.PaymentSummary import Data.Tax.ATO.PrivateHealthInsuranceRebate import Data.Tax.ATO.Rounding @@ -181,7 +204,7 @@ import "Data.Tax.ATO.Pretty" -- Import the tables for the financial year ending 30 June 2024-import qualified "Data.Tax.ATO.FY.FY2024" as FY+import "Data.Tax.ATO.FY.FY2025" -- Convenience function for parsing a Data.Time.Day day :: String -> Day@@ -189,19 +212,19 @@ main :: IO () main = do- let assessment = 'assessTax' FY.tables taxReturn+ let assessment = 'assessTax' tables taxReturn putStrLn . render $ 'Data.Tax.ATO.Pretty.summariseTaxReturnInfo' taxReturn putStrLn "" putStrLn . render $ 'Data.Tax.ATO.Pretty.summariseAssessment' assessment -taxReturn :: 'TaxReturnInfo' FY.FY Rational+taxReturn :: 'TaxReturnInfo' FY Rational taxReturn = 'newTaxReturnInfo'- & set 'paymentSummaries'- [ 'PaymentSummary'- "1234567890" -- ABN- (Money $ 180000) -- Gross payments- (Money 50000) -- Tax withheld- mempty -- Reportable super contributions+ & set 'paymentSummariesIndividualNonBusiness'+ [ 'newPaymentSummaryIndividualNonBusiness' \"53 004 085 616\" -- ABN+ & set 'grossPayments' (Money 180000)+ & set 'totalTaxWithheld' (Money 50000)+ & set 'reportableEmployerSuperannuationContributions' (Money 3000)+ & set 'reportableFringeBenefits' ('fringeBenefitsEmployerNotExempt' $ Money 7274) ] & set 'cgtEvents'@@ -239,20 +262,12 @@ "MBF" "98765432" (Money 250) (Money 60) 'BenefitCode31' ] - & set ('deductions' . 'workRelatedTravelExpenses') (Money 1000)+ & set ('deductions' . 'workRelatedCarExpenses') ('applyCentsPerKilometreMethod' @FY 3333) & set ('deductions' . 'personalSuperannuationContributions') (Money 5000) @ -} --- | 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 = to (foldMap (view taxWithheld))- -- TODO part year spouse newtype SpouseDetails a = SpouseDetails { _spouseTaxableIncome :: Money a@@ -301,46 +316,60 @@ -- -- The following lenses are available: ----- +---------------------------------------+----------------------------------+--- | 'mlsExemption' | Medicare levy exemption |--- +---------------------------------------+----------------------------------+--- | 'helpBalance' | HELP, VSL, SSL, ABSTUDY SSL, |--- | | and TSL account balance |--- +---------------------------------------+----------------------------------+--- | 'sfssBalance' | SFSS account balance |--- +---------------------------------------+----------------------------------+--- | 'paymentSummaries' | PAYG payment summaries |--- +---------------------------------------+----------------------------------+--- | 'interest' | Interest income and tax withheld |--- +---------------------------------------+----------------------------------+--- | '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 |--- +---------------------------------------+----------------------------------++-- +------------------------------------------------------+----------------------------------++-- | 'mlsExemption' | Medicare levy exemption |+-- +------------------------------------------------------+----------------------------------++-- | 'helpBalance' | HELP, VSL, SSL, ABSTUDY SSL, |+-- | | and AASL/TSL account balance |+-- +------------------------------------------------------+----------------------------------++-- | 'sfssBalance' | SFSS account balance |+-- +------------------------------------------------------+----------------------------------++-- | 'paymentSummariesIndividualNonBusiness' | PAYG payment summaries - |+-- | | individual non-business |+-- +------------------------------------------------------+----------------------------------++-- | 'paymentSummariesForeignEmployment' | PAYG payment summaries - |+-- | | foreign employment |+-- +------------------------------------------------------+----------------------------------++-- | 'paymentSummariesBusinessAndPersonalServicesIncome' | PAYG payment summaries - |+-- | | business and personal services |+-- | | income |+-- +------------------------------------------------------+----------------------------------++-- | 'paymentSummariesWithholdingWhereABNNotQuoted' | PAYG payment summaries - |+-- | | withholding where ABN not quoted |+-- +------------------------------------------------------+----------------------------------++-- | 'interest' | Interest income and tax withheld |+-- +------------------------------------------------------+----------------------------------++-- | '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 { _mlsExemption :: Days y , _helpBalance :: Money a , _sfssBalance :: Money a- , _paymentSummaries :: [PaymentSummary a]+ , _paymentSummariesIndividualNonBusiness :: [PaymentSummaryIndividualNonBusiness a]+ , _paymentSummariesForeignEmployment :: [PaymentSummaryForeignEmployment a]+ , _paymentSummariesBusinessAndPersonalServicesIncome :: [PaymentSummaryBusinessAndPersonalServicesIncome a]+ , _paymentSummariesWithholdingWhereABNNotQuoted :: [PaymentSummaryWithholdingWhereABNNotQuoted a] , _interest :: GrossAndWithheld a , _dividends :: [Dividend a]- , _ess :: ESSStatement a+ , _ess :: [ESSStatement a] , _foreignIncome :: Money a , _cgtEvents :: [CGTEvent a] , _deductions :: Deductions a@@ -366,7 +395,10 @@ daysAll -- MLS exemption mempty -- HELP mempty -- SFSS- mempty -- payment summaries+ [] -- payment summaries - individual non-business+ [] -- payment summaries - foreign employment+ [] -- payment summaries - business and personal services income+ [] -- payment summaries - withholding where ABN not quoted mempty -- interest mempty -- dividends mempty -- ESS@@ -408,16 +440,34 @@ mlsExemption :: Lens' (TaxReturnInfo y a) (Days y) mlsExemption = lens _mlsExemption (\s b -> s { _mlsExemption = b }) -paymentSummaries :: Lens' (TaxReturnInfo y a) [PaymentSummary a]-paymentSummaries = lens _paymentSummaries (\s b -> s { _paymentSummaries = b })+paymentSummariesIndividualNonBusiness :: Lens' (TaxReturnInfo y a) [PaymentSummaryIndividualNonBusiness a]+paymentSummariesIndividualNonBusiness =+ lens _paymentSummariesIndividualNonBusiness (\s b -> s { _paymentSummariesIndividualNonBusiness = b }) +paymentSummariesForeignEmployment :: Lens' (TaxReturnInfo y a) [PaymentSummaryForeignEmployment a]+paymentSummariesForeignEmployment =+ lens _paymentSummariesForeignEmployment (\s b -> s { _paymentSummariesForeignEmployment = b })++paymentSummariesBusinessAndPersonalServicesIncome :: Lens' (TaxReturnInfo y a) [PaymentSummaryBusinessAndPersonalServicesIncome a]+paymentSummariesBusinessAndPersonalServicesIncome =+ lens _paymentSummariesBusinessAndPersonalServicesIncome (\s b -> s { _paymentSummariesBusinessAndPersonalServicesIncome = b })++paymentSummariesWithholdingWhereABNNotQuoted :: Lens' (TaxReturnInfo y a) [PaymentSummaryWithholdingWhereABNNotQuoted a]+paymentSummariesWithholdingWhereABNNotQuoted =+ lens _paymentSummariesWithholdingWhereABNNotQuoted (\s b -> s { _paymentSummariesWithholdingWhereABNNotQuoted = b })++-- | Deprecated synonym for 'paymentSummariesIndividualNonBusiness'+paymentSummaries :: Lens' (TaxReturnInfo y a) [PaymentSummaryIndividualNonBusiness a]+paymentSummaries = paymentSummariesIndividualNonBusiness+{-# DEPRECATED paymentSummaries "use 'paymentSummariesIndividualNonBusiness'" #-}+ interest :: Lens' (TaxReturnInfo y a) (GrossAndWithheld a) interest = lens _interest (\s b -> s { _interest = b }) dividends :: Lens' (TaxReturnInfo y a) [Dividend a] dividends = lens _dividends (\s b -> s { _dividends = b }) -ess :: Lens' (TaxReturnInfo y a) (ESSStatement a)+ess :: Lens' (TaxReturnInfo y a) [ESSStatement a] ess = lens _ess (\s b -> s { _ess = b }) foreignIncome :: Lens' (TaxReturnInfo y a) (Money a)@@ -448,9 +498,12 @@ data TaxAssessment a = TaxAssessment { _taxableIncome :: Money a , _taxDue :: Money a+ , _taSpouseContributionOffset :: Money a+ , _taForeignIncomeTaxOffset :: Money a+ , _taFrankingCreditOffset :: Money a , _medicareLevyDue :: Money a+ , _medicareLevySurchargeDue :: Money a , _taxWithheld :: Money a- , _taxCreditsAndOffsets :: Money a , _taCGTAssessment :: CGTAssessment a , _phiAdj :: Money a , _studyAndTrainingLoanRepayment :: Money a@@ -463,15 +516,29 @@ instance HasTaxWithheld TaxAssessment a a where taxWithheld = to _taxWithheld -taxDue :: Getter (TaxAssessment a) (Money a)-taxDue = to _taxDue+taxDue :: Lens' (TaxAssessment a) (Money a)+taxDue = lens _taxDue (\s b -> s { _taxDue = b }) -medicareLevyDue :: Getter (TaxAssessment a) (Money a)-medicareLevyDue = to _medicareLevyDue+offsetForSuperannuationContributionsOnBehalfOfYourSpouse :: Lens' (TaxAssessment a) (Money a)+offsetForSuperannuationContributionsOnBehalfOfYourSpouse =+ lens _taSpouseContributionOffset (\s b -> s { _taSpouseContributionOffset = b }) -taxCreditsAndOffsets :: Getter (TaxAssessment a) (Money a)-taxCreditsAndOffsets = to _taxCreditsAndOffsets+foreignIncomeTaxOffsets :: Lens' (TaxAssessment a) (Money a)+foreignIncomeTaxOffsets =+ lens _taForeignIncomeTaxOffset (\s b -> s { _taForeignIncomeTaxOffset = b }) +frankingCreditOffset :: Lens' (TaxAssessment a) (Money a)+frankingCreditOffset =+ lens _taFrankingCreditOffset (\s b -> s { _taFrankingCreditOffset = b })++medicareLevyDue :: Lens' (TaxAssessment a) (Money a)+medicareLevyDue =+ lens _medicareLevyDue (\s b -> s { _medicareLevyDue = b })++medicareLevySurchargeDue :: Lens' (TaxAssessment a) (Money a)+medicareLevySurchargeDue =+ lens _medicareLevySurchargeDue (\s b -> s { _medicareLevySurchargeDue = b })+ taxCGTAssessment :: Lens' (TaxAssessment a) (CGTAssessment a) taxCGTAssessment = lens _taCGTAssessment (\s b -> s { _taCGTAssessment = b }) @@ -488,17 +555,27 @@ -- | 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 = to $ \a ->- view taxWithheld a- $-$ view taxDue a- $-$ view medicareLevyDue a- $-$ view studyAndTrainingLoanRepayment a- $-$ view privateHealthInsuranceRebateAdjustment a- $+$ view taxCreditsAndOffsets a- $+$ view paygInstalmentsCredit a+taxBalance :: (Num a, Ord a) => Getter (TaxAssessment a) (Money a)+taxBalance = to $ fmap negate . \a ->+ max (Money 0) (+ -- tax on taxable income+ view taxDue a+ -- less non-refundable offsets+ $-$ view offsetForSuperannuationContributionsOnBehalfOfYourSpouse a+ $-$ view foreignIncomeTaxOffsets a+ )+ -- less refundable tax offsets+ $-$ view frankingCreditOffset a+ -- plus other liabilities+ $+$ view medicareLevyDue a+ $+$ view medicareLevySurchargeDue a+ $+$ view privateHealthInsuranceRebateAdjustment a+ $+$ view studyAndTrainingLoanRepayment a+ -- less PAYG credits and other entitlements+ $-$ view taxWithheld a+ $-$ view paygInstalmentsCredit a -instance (Num a, Eq a) => HasCapitalLossCarryForward TaxAssessment a where+instance HasCapitalLossCarryForward TaxAssessment a where capitalLossCarryForward = taxCGTAssessment . capitalLossCarryForward @@ -523,31 +600,16 @@ limit (view helpBalance info) (ttHelp table) <> limit (view sfssBalance info) (ttSfss table) --- | Medicare levy + surcharge-medicareLevyTax- :: (FinancialYear y, Fractional a)- => TaxTables y a- -> TaxReturnInfo y a- -> Tax (Money a) (Money a) -- grand unified individual income tax-medicareLevyTax table info =- let- ml = ttMedicareLevy table- mls = ttMedicareLevySurcharge table- mlsFrac = 1 - getFraction (view mlsExemption info)- in- -- TODO medicare levy exemption- ml- -- FIXME income for MLS purposes includes- -- fringe benefits; family thresholds apply- <> fmap ($* mlsFrac) mls- -- | Taxable income instance (RealFrac a) => HasTaxableIncome (TaxReturnInfo y) a a where taxableIncome = to $ \info -> let cf = view capitalLossCarryForward info gross = foldMap wholeDollars- [ view (paymentSummaries . taxableIncome) info+ [ view (paymentSummariesIndividualNonBusiness . taxableIncome) info+ , view (paymentSummariesForeignEmployment . taxableIncome) info+ , view (paymentSummariesBusinessAndPersonalServicesIncome . taxableIncome) info+ , view (paymentSummariesWithholdingWhereABNNotQuoted . taxableIncome) info , view (interest . taxableIncome) info , view (dividends . taxableIncome) info , view (ess . taxableIncome) info@@ -557,13 +619,67 @@ in wholeDollars (gross $-$ views deductions totalDeductions info) --- | Includes PAYG withholding by employer or bank.--- Does not include franking credits.+-- | Includes PAYG withholding by employer, and TFN+-- amounts withheld e.g. from bank interest, ESS discounts, etc.+--+-- Does not include franking credits (which are a refundable offset).+-- instance (Num a) => HasTaxWithheld (TaxReturnInfo y) a a where taxWithheld = to $ \info ->- view (paymentSummaries . taxWithheld) info+ view (paymentSummariesIndividualNonBusiness . taxWithheld) info+ <> view (paymentSummariesForeignEmployment . taxWithheld) info+ <> view (paymentSummariesBusinessAndPersonalServicesIncome . taxWithheld) info+ <> view (paymentSummariesWithholdingWhereABNNotQuoted . taxWithheld) info <> view (interest . taxWithheld) info+ <> view (ess . taxWithheld) info +fringeBenefits :: (Num a) => TaxReturnInfo y a -> Money a+fringeBenefits info =+ foldOf l'inb info+ <> foldOf l'foreign info+ where+ l'inb =+ paymentSummariesIndividualNonBusiness . traverse+ . reportableFringeBenefits . traverse+ . to (\(ReportableFringeBenefits amount _) -> amount)+ l'foreign =+ paymentSummariesForeignEmployment . traverse+ . reportableFringeBenefits . traverse+ . to (\(ReportableFringeBenefits amount _) -> amount)++reportableSuperContributions :: (Num a) => TaxReturnInfo y a -> Money a+reportableSuperContributions info =+ foldOf (paymentSummariesIndividualNonBusiness . traverse . reportableEmployerSuperannuationContributions) info+ <> foldOf (paymentSummariesForeignEmployment . traverse . reportableEmployerSuperannuationContributions) info+ <> foldOf (paymentSummariesBusinessAndPersonalServicesIncome . traverse . reportableEmployerSuperannuationContributions) info+ <> view (deductions . personalSuperannuationContributions) info++-- | Calculate Division 293 income+division293Income :: (RealFrac a) => TaxReturnInfo y a -> Money a+division293Income info =+ view taxableIncome info+ <> fringeBenefits info+ -- TODO net financial investment loss+ -- TODO net rental property loss+ -- TODO net amount on which family trust distribution has been paid+ -- TODO super lump sum taxed elements with zero tax rate+ -- TODO assessable FHSS released amount++paygInstalmentIncome :: (RealFrac a) => TaxReturnInfo y a -> Money a+paygInstalmentIncome info =+ -- TODO gross rent+ view (dividends . taxableIncome) info+ -- TODO royalties?+ -- TODO foreign pensions assessable in Australia+ -- TODO share of income from partnerships and trusts+ <> view foreignIncome info+ <> view (interest . taxableIncome) info+ -- TODO business income (incl PSI etc)+ <> view (paymentSummariesWithholdingWhereABNNotQuoted . taxableIncome) info+ -- TODO gross income where tax withheld due to not provide TFN+ -- TODO withdrawal from farm management deposits+ -- TODO fuel tax credits+ -- | Assess a tax return, given tax tables and tax return info. assessTax :: (FinancialYear y, RealFrac a)@@ -574,20 +690,47 @@ (view capitalLossCarryForward info) (view cgtEvents info) taxable = view taxableIncome info due = getTax (individualTax tables) taxable- studyRepayment = getTax (studyAndTrainingLoanRepaymentTax tables info) taxable- mlAndMLS = getTax (medicareLevyTax tables info) taxable - incomeForSurchargePurposes =+ exemptForeignIncome =+ foldOf (paymentSummariesIndividualNonBusiness . traverse . exemptForeignEmploymentIncome) info++ repaymentIncome = taxable- -- TODO reportable fringe benefits- -- TODO net investment losses- <> foldOf (paymentSummaries . traverse . to reportableEmployerSuperannuationContributions) info+ <> fringeBenefits info+ -- TODO net financial investment losses+ -- TODO net rental property losses+ <> reportableSuperContributions info+ <> exemptForeignIncome + studyRepayment = getTax (studyAndTrainingLoanRepaymentTax tables info) repaymentIncome++ ml = medicareLevy'+ (ttMedicareLevyRatesAndThresholds tables)+ taxable+ (preview (spouseDetails . traverse . spouseTaxableIncome) info)+ (view (incomeTests . dependentChildren) info)++ surchargeIncome =+ taxable+ <> fringeBenefits info+ -- TODO net financial investment losses+ -- TODO net rental property losses+ <> reportableSuperContributions info+ -- TODO spouse's share of net income of a trust on which the trustee+ -- must pay tax, if not included in taxable income+ <> ( if taxable > mempty then exemptForeignIncome else mempty )+ -- TODO reduction by taxed element of super lump sum++ mls =+ let mlsFrac = 1 - getFraction (view mlsExemption info)+ -- TODO family thresholds apply+ in getTax (fmap ($* mlsFrac) (ttMedicareLevySurcharge tables)) surchargeIncome+ spouseIncomeForSurchargePurposes = fmap (view spouseTaxableIncome) (view spouseDetails info) phiAdj = assessExcessPrivateHealthRebate- incomeForSurchargePurposes+ surchargeIncome spouseIncomeForSurchargePurposes (view (incomeTests . dependentChildren) info) (ttPHIRebateRates tables)@@ -595,7 +738,7 @@ foreignIncomeTaxOffsetLimit = let- step1 = due <> mlAndMLS+ step1 = due <> ml <> mls step2 = let info' = info & set foreignIncome mempty@@ -603,48 +746,41 @@ view taxableIncome info' <> view (deductions . foreignIncomeDeductions) info' due' = getTax (individualTax tables) taxable'- mlAndMLS' = getTax (medicareLevyTax tables info') taxable'+ ml' = medicareLevy'+ (ttMedicareLevyRatesAndThresholds tables)+ taxable+ (preview (spouseDetails . traverse . spouseTaxableIncome) info)+ (view (incomeTests . dependentChildren) info)+ mls' =+ let mlsFrac = 1 - getFraction (view mlsExemption info)+ -- FIXME income for MLS purposes includes fringe benefits; family thresholds apply+ in getTax (fmap ($* mlsFrac) (ttMedicareLevySurcharge tables)) taxable in- due' <> mlAndMLS'+ due' <> ml' <> mls' step3 = step1 $-$ step2 in max (Money 1000) step3 frankingCredit = wholeDollars $ view (dividends . taxWithheld) info- off =- view (offsets . spouseContributionOffset) info- <> min (view (offsets . foreignTaxOffset) info) foreignIncomeTaxOffsetLimit+ spouseContribOffset = view (offsets . spouseContributionOffset) info+ fito = min (view (offsets . foreignTaxOffset) info) foreignIncomeTaxOffsetLimit in TaxAssessment taxable due- mlAndMLS+ spouseContribOffset+ fito+ frankingCredit+ ml+ mls (view taxWithheld info)- (frankingCredit <> off) cg phiAdj studyRepayment (view (offsets . paygInstalments) info) --- | Australian Business Number-type ABN = String --- | PAYG payment summary - individual non-business-data PaymentSummary a = PaymentSummary- { summaryABN :: ABN- , summaryGross :: Money a- , summaryWithheld :: Money a- , reportableEmployerSuperannuationContributions :: Money a- }---- | Gross income-instance HasTaxableIncome PaymentSummary a a where- taxableIncome = to summaryGross--instance HasTaxWithheld PaymentSummary a a where- taxWithheld = to summaryWithheld- -- | A proportion is a non-negative number in interval @[0,1]@. -- Use 'proportion' to construct. newtype Proportion a = Proportion@@ -991,6 +1127,8 @@ -- The following lenses are available: -- -- +------------------------------+--------------------------------------------++-- | 'essEmployerDetails' | 'PayerDetails' for employer. |+-- +------------------------------+--------------------------------------------+ -- | 'essTaxedUpfrontReduction' | __D__ Discount from taxed up front | -- | | schemes—eligible for reduction | -- +------------------------------+--------------------------------------------+@@ -1009,18 +1147,24 @@ -- +------------------------------+--------------------------------------------+ -- data ESSStatement a = ESSStatement- { _taxedUpfrontReduction :: Money a+ { _essPayer :: PayerDetails+ , _taxedUpfrontReduction :: Money a , _taxedUpfrontNoReduction :: Money a , _deferral :: Money a , _pre2009 :: Money a , _tfnAmounts :: Money a , _foreignSourceDiscounts :: Money a }+ deriving (Eq, Ord) -- | Construct an 'ESSStatement' with all amounts at /zero/.-newESSStatement :: Num a => ESSStatement a-newESSStatement = ESSStatement mempty mempty mempty mempty mempty mempty+newESSStatement :: (Num a) => PayerDetails -> ESSStatement a+newESSStatement payer = ESSStatement payer mempty mempty mempty mempty mempty mempty +-- | Employer details+essEmployerDetails :: Lens' (ESSStatement a) PayerDetails+essEmployerDetails = lens _essPayer (\s b -> s { _essPayer = b })+ -- | Discount from taxed up front schemes—eligible for reduction. -- Item __D__ in /Employee share schemes/ section. essTaxedUpfrontReduction :: Lens' (ESSStatement a) (Money a)@@ -1064,10 +1208,5 @@ <> view essDeferral s <> view essPre2009 s -instance (Num a) => Semigroup (ESSStatement a) where- ESSStatement a b c d e f <> ESSStatement a' b' c' d' e' f' =- ESSStatement (a <> a') (b <> b') (c <> c') (d <> d') (e <> e') (f <> f')--instance (Num a) => Monoid (ESSStatement a) where- mempty = newESSStatement- mappend = (<>)+instance HasTaxWithheld ESSStatement a a where+ taxWithheld = essTFNAmounts
+ src/Data/Tax/ATO/ABN.hs view
@@ -0,0 +1,94 @@+-- This file is part of hs-tax-ato+-- Copyright (C) 2025 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/>.++{-|++Australian Business Number (ABN) types and functions.++@+import qualified Data.Tax.ATO.ABN as ABN++main = do+ let+ abnStr = "53 004 085 616"+ Just abn = ABN.parse abnStr+ abnInt = ABN.asInt abn+ Just abn' = ABN.fromInt abnInt+ putStrLn $ ABN.asString abn' -- prints "53 004 085 616"+@++It is recommended to import this module qualified.++You can use the @OverloadedStrings@ language extension or the 'parse' function+to convert string to ABNs. Space characters are ignored, but other non-digits+will cause parse failure.++-}++module Data.Tax.ATO.ABN+ (+ ABN+ , parse+ , fromInt+ , asString+ , asInt+ ) where++import Data.Char (isDigit)+import Data.String+import Data.Maybe (fromJust)++-- | Australian Business Number (ABN)+newtype ABN = ABN Int+ deriving (Eq, Ord, Show)++-- | Parse an ABN, throwing an error if it is not valid.+instance IsString ABN where+ fromString = fromJust . parse++-- | Construct an ABN, checking validity.+fromInt :: Int -> Maybe ABN+fromInt n | valid n = Just (ABN n)+fromInt _ = Nothing++-- | Parse an ABN. Spaces characters are allowed, other non-digit+-- characters are not.+parse :: String -> Maybe ABN+parse s+ | all isDigit s' = fromInt (read s')+ | otherwise = Nothing+ where s' = filter (/= ' ') s++valid :: Int -> Bool+valid n =+ (== 0) . (`mod` 89) . subtract 10 . snd $ foldr step (n, 0) weights+ where+ weights = [10,1,3,5,7,9,11,13,15,17,19]+ step weight (n',acc) = ((+ acc) . (* weight)) <$> divMod n' 10++asInt :: ABN -> Int+asInt (ABN n) = n++-- Format ABN in the standard way (XX XXX XXX XXX)+asString :: ABN -> String+asString (ABN n) =+ case s' of+ [a1,a2,b1,b2,b3,c1,c2,c3,d1,d2,d3] -> [a1,a2,' ',b1,b2,b3,' ',c1,c2,c3,' ',d1,d2,d3]+ _ -> show n -- can't happen, but just in case...+ where+ n' = abs n -- negative can't happen, but just in case...+ s = show n'+ s' = replicate (11 - length s) '0' <> s -- left-pad to 11 digits
src/Data/Tax/ATO/CGT.hs view
@@ -27,9 +27,6 @@ -} -{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}- module Data.Tax.ATO.CGT ( -- * CGT events@@ -37,11 +34,12 @@ -- * CGT assessments for tax returns , assessCGTEvents- , CGTAssessment(CGTAssessment)- , CGTNetGainOrLoss(..)+ , CGTAssessment+ , nullCGTAssessment , HasCapitalLossCarryForward(..)- , cgtNetGainOrLoss , cgtNetGain+ , cgtTotalCurrentYearGains+ , cgtNetLossesCarriedForward -- * CGT computations , HasCapitalGain(..)@@ -49,7 +47,6 @@ , isCapitalGain , isCapitalLoss , discountApplicable- , netCapitalGainOrLoss ) where import Data.Foldable (toList)@@ -139,34 +136,6 @@ capitalGain = to (foldMap (view capitalGain)) ---- | Compute the /discounted/ gain or carry-forward loss------ Losses are used to offset non-discountable capital gains--- first, then discountable gains, before the discount is applied--- to discountable gains.------ *Does not implement the indexation method for cost-base reduction!*----netCapitalGainOrLoss- :: (Fractional a, Ord a, Foldable t)- => Money a -- ^ loss carried forward- -> t (CGTEvent a) -- ^ CGT events- -> CGTNetGainOrLoss a-netCapitalGainOrLoss carry events =- let- l = toList events- (discountableGain, nonDiscountableGain) =- over both (view capitalGain) (partition discountApplicable l)- loss = foldMap capitalLoss l- (nonDiscLessLoss, remLoss) = sub nonDiscountableGain (loss <> carry)- (discLessLoss, finalLoss) = sub discountableGain remLoss- discGain = nonDiscLessLoss <> (discLessLoss $* 0.5)- in- if discGain > mempty- then CGTNetGain discGain- else CGTLoss finalLoss- -- | @sub x y@ = subtract @y@ from @x@, clamping to 0 and -- returning @(result, leftovers)@ --@@ -176,56 +145,88 @@ in (max mempty r, over money abs (min mempty r)) -- | Assess the total capital gains and net capital gain or loss.+--+-- Losses are used to offset non-discountable capital gains+-- first, then discountable gains, before the discount is applied+-- to discountable gains.+--+-- __Does not implement the indexation method for cost-base reduction.__+-- assessCGTEvents :: (Fractional a, Ord a, Foldable t) => Money a -- ^ capital loss carried forward -> t (CGTEvent a) -> CGTAssessment a-assessCGTEvents carry evs = CGTAssessment- (view capitalGain evs)- (netCapitalGainOrLoss carry evs)+assessCGTEvents carry events =+ let+ l = toList events+ (discountableGain, nonDiscountableGain) =+ over both (view capitalGain) (partition discountApplicable l)+ totalGain = discountableGain <> nonDiscountableGain+ totalLoss = foldMap capitalLoss l+ (nonDiscountableGainLossesApplied, unappliedLosses) = sub nonDiscountableGain (totalLoss <> carry)+ (discountableGainLossesApplied, finalUnappliedLosses) = sub discountableGain unappliedLosses+ discount = discountableGainLossesApplied $* 0.5+ discountedGain = nonDiscountableGainLossesApplied <> (discountableGainLossesApplied $-$ discount) + lossesApplied = (totalLoss <> carry) $-$ finalUnappliedLosses+ priorYearLossesApplied = min carry lossesApplied+ currentYearLossesApplied = lossesApplied $-$ priorYearLossesApplied+ in+ CGTAssessment+ totalGain+ totalLoss+ currentYearLossesApplied+ priorYearLossesApplied+ finalUnappliedLosses+ discount+ discountedGain+ -- | Total undiscounted gains and net gain/loss for tax assessment data CGTAssessment a = CGTAssessment- { _cgtaTotal :: Money a- , _cgtaNet :: CGTNetGainOrLoss a+ { _totalCurrentYearCapitalGains :: Money a+ , _totalCurrentYearCapitalLosses :: Money a+ , _totalCurrentYearCapitalLossesApplied :: Money a+ , _totalPriorYearCapitalLossesApplied :: Money a+ , _netCapitalLossesCarriedForward :: Money a+ , _totalCGTDiscountApplied :: Money a+ , _netCapitalGain :: Money a }- deriving (Show)--instance Functor CGTAssessment where- fmap f (CGTAssessment a b) = CGTAssessment (fmap f a) (fmap f b)+ deriving (Eq) -instance HasCapitalGain CGTAssessment a a where- capitalGain = to _cgtaTotal+-- | A 'CGTAssessment' whose values are all zero+nullCGTAssessment :: (Num a) => CGTAssessment a+nullCGTAssessment = CGTAssessment mempty mempty mempty mempty mempty mempty mempty --- | The 'CGTNetGainOrLoss' value of the 'CGTAssessment'-cgtNetGainOrLoss :: Lens' (CGTAssessment a) (CGTNetGainOrLoss a)-cgtNetGainOrLoss = lens _cgtaNet (\s b -> s { _cgtaNet = b })+instance Functor CGTAssessment where+ fmap f (CGTAssessment a b c d e g h) = CGTAssessment+ (fmap f a)+ (fmap f b)+ (fmap f c)+ (fmap f d)+ (fmap f e)+ (fmap f g)+ (fmap f h) --- | The net capital gain, or zero if a loss.-cgtNetGain :: (Num a) => Getter (CGTAssessment a) (Money a)-cgtNetGain = cgtNetGainOrLoss . to f- where- f (CGTNetGain a) = a- f _ = mempty+-- | __18A__ The net capital gain, or zero if a loss.+cgtNetGain :: Lens' (CGTAssessment a) (Money a)+cgtNetGain = lens _netCapitalGain (\s b -> s { _netCapitalGain = b }) --- | A net (loss offset, discounted) gain, or the loss amount-data CGTNetGainOrLoss a = CGTNetGain (Money a) | CGTLoss (Money a)- deriving (Show)+-- | __18H__ Total current year capital gains+cgtTotalCurrentYearGains :: Lens' (CGTAssessment a) (Money a)+cgtTotalCurrentYearGains =+ lens _totalCurrentYearCapitalGains (\s b -> s { _totalCurrentYearCapitalGains = b }) -instance Functor CGTNetGainOrLoss where- fmap f (CGTNetGain a) = CGTNetGain (fmap f a)- fmap f (CGTLoss a) = CGTLoss (fmap f a)+-- | __18V__ Net capital losses carried forward to later income years+cgtNetLossesCarriedForward :: Lens' (CGTAssessment a) (Money a)+cgtNetLossesCarriedForward =+ lens _netCapitalLossesCarriedForward (\s b -> s { _netCapitalLossesCarriedForward = b }) -- | Types that have a carry-forward capital loss (either as an -- input or an output). class HasCapitalLossCarryForward a b where capitalLossCarryForward :: Lens' (a b) (Money b) -instance (Num a, Eq a) => HasCapitalLossCarryForward CGTNetGainOrLoss a where- capitalLossCarryForward = lens- (\s -> case s of CGTLoss a -> a ; _ -> mempty)- (\s b -> if b == mempty then s else CGTLoss b)--instance (Num a, Eq a) => HasCapitalLossCarryForward CGTAssessment a where- capitalLossCarryForward = cgtNetGainOrLoss . capitalLossCarryForward+instance HasCapitalLossCarryForward CGTAssessment a where+ capitalLossCarryForward =+ lens _netCapitalLossesCarriedForward (\s b -> s { _netCapitalLossesCarriedForward = b })
src/Data/Tax/ATO/Common.hs view
@@ -20,9 +20,9 @@ -} -{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE UndecidableInstances #-} module Data.Tax.ATO.Common (@@ -31,7 +31,12 @@ -- * Classes , HasTaxableIncome(..)+ , HasTaxWithheld(..) + -- * Medicare levy+ , MedicareLevyRatesAndThresholds(..)+ , medicareLevy'+ -- * Common taxes and helpers , medicareLevy , lowIncomeTaxOffset@@ -39,6 +44,17 @@ , lamito , corporateTax + -- * Deduction rates that vary by financial year+ , applyCentsPerKilometreMethod+ , HasCentsPerKilometreMethod++ , applyFixedRateMethod+ , HasFixedRateMethod+ , applyFixedRateMethodPre2023+ , HasFixedRateMethodPre2023+ , applyShortcutMethod+ , HasShortcutMethod+ -- * Convenience functions , thresholds' , marginal'@@ -46,14 +62,17 @@ import Control.Lens (Getter, review, to, view) import Data.Bifunctor (first)+import Data.Proxy+import GHC.TypeLits import Data.Tax import Data.Tax.ATO.PrivateHealthInsuranceRebate+import Data.Tax.ATO.FY -- | A set of tax tables for a particular financial year data TaxTables y a = TaxTables { ttIndividualIncomeTax :: Tax (Money a) (Money a)- , ttMedicareLevy :: Tax (Money a) (Money a)+ , ttMedicareLevyRatesAndThresholds :: MedicareLevyRatesAndThresholds a , ttMedicareLevySurcharge :: Tax (Money a) (Money a) , ttHelp :: Tax (Money a) (Money a) , ttSfss :: Tax (Money a) (Money a)@@ -62,6 +81,40 @@ , ttPHIRebateRates :: PrivateHealthInsuranceRebateRates a } ++data MedicareLevyRatesAndThresholds a = MedicareLevyRatesAndThresholds+ { medicareLevyRate :: a+ , medicareLevyThresholdIndividual :: Money a+ , medicareLevyThresholdIndividualSeniorAndPensioner :: Money a+ , medicareLevyThresholdFamily :: Money a+ , medicareLevyThresholdFamilySeniorAndPensioner :: Money a+ , medicareLevyThresholdDependentChildIncrease :: Money a+ }++medicareLevy'+ :: (Fractional a, Ord a)+ => MedicareLevyRatesAndThresholds a+ -> Money a -- ^ taxable income+ -> Maybe (Money a) -- ^ spouse taxable income+ -> Integer -- ^ number of dependents+ -> Money a+medicareLevy' rates me mYou nDeps = case mYou of+ Nothing | nDeps <= 0 ->+ let+ t = medicareLevyThresholdIndividual rates+ in+ getTax (mk t) me+ _ ->+ let+ t = medicareLevyThresholdFamily rates+ $+$ fromIntegral nDeps *$ medicareLevyThresholdDependentChildIncrease rates+ combinedIncome = maybe me (me $+$) mYou+ in+ (me $/$ combinedIncome) *$ getTax (mk t) combinedIncome+ where+ mk l = lesserOf (above l 0.1) (flat (medicareLevyRate rates))++ -- | The Medicare levy, incorporating the Medicare levy reduction. -- The rate is 10% of the income above the given shade-in threshold -- or 2% of the total income, whichever is less.@@ -116,3 +169,164 @@ => HasTaxableIncome t (x a) a where taxableIncome = to (foldMap (view taxableIncome))++-- | Types 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 = to (foldMap (view taxWithheld))+++-- | See 'applyCentsPerKilometreMethod'.+class HasCentsPerKilometreMethod y where+ centsPerKilometre :: Num a => a++instance (2016 <= y, y <= 2025, FinancialYear y) => HasCentsPerKilometreMethod y where+ centsPerKilometre = case fromProxy (Proxy @y) of+ y | y == 2025 -> 88+ | y == 2024 -> 85+ | y == 2023 -> 78+ | y > 2020, y <= 2022 -> 72+ | y > 2018, y <= 2020 -> 68+ | y > 2015, y <= 2018 -> 66+ | otherwise -> 0 -- can't happen++-- | Apply the single-rate cents per kilometre method (in use since+-- the 2015–16 FY). Clamped (by law) at 5000 kms. Use+-- @TypeApplications@ to specify the financial year, e.g.+--+-- @+-- import Data.Tax.ATO.FY.2025 (FY)+--+-- y = applyCentsPerKilometreMethod \@2025 1111 -- using type literal+-- x = applyCentsPerKilometreMethod \@FY 1111 -- same thing, using type synonym+-- @+--+applyCentsPerKilometreMethod+ :: forall y a. (HasCentsPerKilometreMethod y, Fractional a, Ord a)+ => a -> Money a+applyCentsPerKilometreMethod kms = Money $ centsPerKilometre @y * min kms 5000 / 100+++-- | See 'applyFixedRateMethod'+class HasFixedRateMethod y where+ fixedRateMethodCentsPerHour :: Num a => a++instance HasFixedRateMethod 2023 where+ fixedRateMethodCentsPerHour = 67+instance HasFixedRateMethod 2024 where+ fixedRateMethodCentsPerHour = 67+instance HasFixedRateMethod 2025 where+ fixedRateMethodCentsPerHour = 70++-- | The updated fixed rate method available from the 2022–23 income+-- year. It covers:+--+-- * home and mobile internet or data expenses+-- * mobile and home phone usage expenses+-- * electricity and gas (energy expenses) for heating, cooling and lighting+-- * stationery and computer consumables, such as printer ink and paper.+--+-- You can separately claim deductions for work-related use of+-- technology and office furniture, and (in limited circumstances)+-- occupancy expenses and cleaning expenses.+--+-- Use @TypeApplications@ to specify the financial year, e.g.+--+-- @+-- import Data.Tax.ATO.FY.2025 (FY)+--+-- y = applyFixedRateMethod \@2025 1111 -- using type literal+-- x = applyFixedRateMethod \@FY 1111 -- same thing, using type synonym+-- @+--+-- For earlier income years use 'applyFixedRateMethodPre2023'.+--+applyFixedRateMethod+ :: forall y a. (HasFixedRateMethod y, Fractional a)+ => a -> Money a+applyFixedRateMethod hours = Money $ fixedRateMethodCentsPerHour @y * hours / 100+++-- | See 'applyShortcutMethod'+class HasShortcutMethod y where+ shortcutMethodCentsPerHour :: Num a => a++instance (2020 <= y, y <= 2022) => HasShortcutMethod y where+ shortcutMethodCentsPerHour = 80++-- | The shortcut method for working from home deductions was+-- available from 1 March 2020 to 30 June 2020 in the 2019–20 income+-- year, and for the 2020–21 and 2021–22 income years. It covers:+--+-- * phone and data expenses+-- * internet expenses+-- * the decline in value of equipment and furniture+-- * electricity and gas (energy expenses) for heating, cooling and lighting.+--+-- Use @TypeApplications@ to specify the financial year, e.g.+--+-- @+-- import Data.Tax.ATO.FY.2025 (FY)+--+-- y = applyShortcutMethod \@2025 1111 -- using type literal+-- x = applyShortcutMethod \@FY 1111 -- same thing, using type synonym+-- @+--+applyShortcutMethod+ :: forall y a. (HasShortcutMethod y, Fractional a)+ => a -> Money a+applyShortcutMethod hours = Money $ shortcutMethodCentsPerHour @y * hours / 100+++-- | See 'applyFixedRateMethodPre2023'+class HasFixedRateMethodPre2023 y where+ fixedRateMethodPre2023CentsPerHour :: Num a => a++instance (2002 <= y, y <= 2022, FinancialYear y) => HasFixedRateMethodPre2023 y where+ fixedRateMethodPre2023CentsPerHour = case fromProxy (Proxy @y) of+ y | y > 2018, y <= 2022 -> 52+ | y > 2014, y <= 2018 -> 45+ | y > 2010, y <= 2014 -> 34+ | y > 2004, y <= 2010 -> 26+ | y > 2001, y <= 2004 -> 20+ | otherwise -> 0 -- can't happen++-- | The fixed rate method available up to the 2021–22 income year.+-- It differs from the current fixed rate method (see+-- 'HasFixedRateMethod') in which categories of expenses are+-- included. This method covers:+--+-- * the decline in value of home office furniture and+-- furnishings – for example, a desk+-- * electricity and gas (energy expenses) for heating,+-- cooling and lighting+-- * cleaning your dedicated home office.+--+-- You should separately claim for:+--+-- * home phone and internet expenses, including the decline in+-- value of the handset+-- * stationery and computer consumables, such as printer ink+-- and paper+-- * decline in value of depreciating assets other than+-- home office furniture and furnishings used for work+-- purposes – for example, computers and laptops.+--+-- Use @TypeApplications@ to specify the financial year, e.g.+--+-- @+-- import Data.Tax.ATO.FY.2025 (FY)+--+-- y = applyFixedRateMethodPre2023 \@2025 1111 -- using type literal+-- x = applyFixedRateMethodPre2023 \@FY 1111 -- same thing, using type synonym+-- @+--+-- For later income years, use 'applyFixedRateMethod'.+--+applyFixedRateMethodPre2023+ :: forall y a. (HasFixedRateMethodPre2023 y, Fractional a)+ => a -> Money a+applyFixedRateMethodPre2023 hours = Money $ fixedRateMethodPre2023CentsPerHour @y * hours / 100
+ src/Data/Tax/ATO/Depreciation.hs view
@@ -0,0 +1,87 @@++{-|++Types and computations for calculating decline in value.++-}++module Data.Tax.ATO.Depreciation+ ( DepreciatingAsset(..)+ , EffectiveLife+ , DepreciationMethod+ , diminishingValueMethod+ , primeCostMethod+ , depreciationSchedule+ , declineInValue+ ) where++import Data.Proxy (Proxy(..))++import Data.Time (Day, Year, diffDays, fromGregorian)++import Data.Tax+import Data.Tax.ATO.FY++-- | Effective life in years+type EffectiveLife = Rational++data DepreciatingAsset a = DepreciatingAsset+ Day -- ^ Start date of decline in value+ (Money a) -- ^ Asset's cost+ EffectiveLife -- ^ Effective life, in years.+ (DepreciationMethod a)++-- | Given the start date, effective life and the pair+-- @(cost, baseValue)@, calculate the decline in value over+-- a full year (i.e. /days held/ = 365).+--+type DepreciationMethod a =+ Day -> EffectiveLife -> (Money a, Money a) -> Money a++-- | Decline in value = @remainingValue * r / effectiveLife@,+-- where @r = 1.5@ for assets acquired before 2006-05-10,+-- otherwise @2.0@.+diminishingValueMethod :: (Fractional a) => DepreciationMethod a+diminishingValueMethod start life = ($/ fromRational life) . ($* factor) . snd+ where+ factor | start < fromGregorian 2006 05 10 = 1.5+ | otherwise = 2++-- | /Straight-line depreciation/.+-- Decline in value = cost / effective life.+primeCostMethod :: (Fractional a) => DepreciationMethod a+primeCostMethod _ life = ($/ fromRational life) . fst++-- | Calculate decline in value over financial years+depreciationSchedule+ :: (Fractional a, Ord a)+ => DepreciatingAsset a -> [(Year, Money a)]+depreciationSchedule (DepreciatingAsset t1 cost life method) =+ let+ fy = financialYear t1+ (_, eofy) = financialYearRange fy+ daysList = diffDays eofy t1 + 1 : fmap daysInYear [fy + 1..]++ step (_, value) nDays =+ let+ decline = (fromIntegral nDays *$ method t1 life (cost, value)) $/ 365+ in+ if decline > value+ then (value, Money 0)+ else (decline, value $-$ decline)+ in+ zip [fy..]+ . takeWhile (>= Money 1)+ . fmap fst+ . drop 1+ $ scanl step (Money 0, cost) daysList++-- | Calculate decline in value for the given financial year+-- (financial year given as type, via 'Proxy').+declineInValue+ :: (FinancialYear y, Fractional a, Ord a)+ => Proxy y -> DepreciatingAsset a -> Money a+declineInValue proxy asset =+ case dropWhile ((< fromProxy proxy) . fst) (depreciationSchedule asset) of+ (y,r):_ | y == fromProxy proxy -> r+ _ -> Money 0
src/Data/Tax/ATO/FY.hs view
@@ -20,10 +20,7 @@ -} -{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE ScopedTypeVariables #-} module Data.Tax.ATO.FY ( Days@@ -33,9 +30,12 @@ , getDays , getFraction , FinancialYear+ , fromProxy , financialYear , financialYearRange , financialYearRangeFromProxy+ , daysInYear+ , daysInYearFromProxy ) where @@ -47,11 +47,19 @@ type FinancialYear = KnownNat -daysInYear :: KnownNat n => Proxy n -> Integer-daysInYear proxy- | isLeapYear (natVal proxy) = 366- | otherwise = 365+fromProxy :: (FinancialYear y) => Proxy y -> Year+fromProxy = natVal +-- | Number of days in the financial year ending June 30 of the given year.+daysInYear :: Year -> Integer+daysInYear y+ | isLeapYear y = 366+ | otherwise = 365++-- | Number of days in the financial year ending June 30 (type-level variant).+daysInYearFromProxy :: FinancialYear y => Proxy y -> Integer+daysInYearFromProxy = daysInYear . natVal+ -- | Some number of days in a year. Use 'days' to construct. newtype Days (n :: Nat) = Days { getDays :: Integer@@ -62,11 +70,11 @@ -- | Construct a 'Days' value. If out of range, the number of days -- is clamped to 0 or 365/366 (no runtime errors). days :: forall a. (FinancialYear a) => Integer -> Days a-days = Days . max 0 . min (daysInYear (Proxy :: Proxy a))+days = Days . max 0 . min (daysInYearFromProxy (Proxy :: Proxy a)) -- | Every day of the year daysAll :: forall a. (FinancialYear a) => Days a-daysAll = Days (daysInYear (Proxy :: Proxy a))+daysAll = Days (daysInYearFromProxy (Proxy :: Proxy a)) -- | Zero days of the year daysNone :: Days a@@ -76,7 +84,7 @@ -- The denominator is determined by the year type. -- getFraction :: forall a frac. (FinancialYear a, Fractional frac) => Days a -> frac-getFraction n = fromRational $ getDays n % daysInYear (Proxy :: Proxy a)+getFraction n = fromRational $ getDays n % daysInYearFromProxy (Proxy :: Proxy a) -- | The financial year in which the given day falls. --
src/Data/Tax/ATO/FY/FY2017.hs view
@@ -17,13 +17,18 @@ {-# LANGUAGE DataKinds #-} -- | Tax tables for 2016–17 financial year.-module Data.Tax.ATO.FY.FY2017 (tables, individualIncomeTax) where+module Data.Tax.ATO.FY.FY2017 (FY, fyProxy, tables, individualIncomeTax) where -import Control.Lens (review)+import Data.Proxy+ import Data.Tax import Data.Tax.ATO.Common import Data.Tax.ATO.PrivateHealthInsuranceRebate +type FY = 2017+fyProxy :: Proxy FY+fyProxy = Proxy+ -- | In FY2017 the 37% threshold was raised from $80,000 to $87,000 -- individualIncomeTax :: (Fractional a, Ord a) => Tax (Money a) (Money a)@@ -34,7 +39,7 @@ , (180000, 0.45 - 0.37) ] temporaryBudgetRepairLevy :: (Fractional a, Ord a) => Tax (Money a) (Money a)-temporaryBudgetRepairLevy = above (review money 180000) 0.02+temporaryBudgetRepairLevy = above (Money 180000) 0.02 help, sfss :: (Fractional a, Ord a) => Tax (Money a) (Money a) help = thresholds'@@ -43,6 +48,16 @@ , (82551, 0.005), (86895, 0.005), (95627, 0.005), (101900, 0.005) ] sfss = thresholds' [(54869, 0.02), (67369, 0.01), (95627, 0.01)] +medicare :: (Fractional a) => MedicareLevyRatesAndThresholds a+medicare = MedicareLevyRatesAndThresholds+ { medicareLevyRate = 0.02+ , medicareLevyThresholdIndividual = Money 21655+ , medicareLevyThresholdIndividualSeniorAndPensioner = Money 34244+ , medicareLevyThresholdFamily = Money 36541+ , medicareLevyThresholdFamilySeniorAndPensioner = Money 47670+ , medicareLevyThresholdDependentChildIncrease = Money 3356+ }+ -- | /Medicare levy surcharge (MLS)/. Certain exemptions are available. -- -- __Known issues__: the MLS is levied on taxable income + fringe@@ -64,7 +79,7 @@ tables :: (Ord a, Fractional a) => TaxTables 2017 a tables = TaxTables (individualIncomeTax <> temporaryBudgetRepairLevy)- (medicareLevy (review money 21656))+ medicare medicareLevySurcharge help sfss
src/Data/Tax/ATO/FY/FY2018.hs view
@@ -20,7 +20,6 @@ module Data.Tax.ATO.FY.FY2018 (FY, fyProxy, tables) where import Data.Proxy-import Control.Lens (review) import Data.Tax import Data.Tax.ATO.Common import Data.Tax.ATO.PrivateHealthInsuranceRebate@@ -37,6 +36,16 @@ , (84063, 0.005), (88487, 0.005), (97378, 0.005), (103766, 0.005) ] sfss = thresholds' [(55874, 0.02), (68603, 0.01), (97378, 0.01)] +medicare :: (Fractional a) => MedicareLevyRatesAndThresholds a+medicare = MedicareLevyRatesAndThresholds+ { medicareLevyRate = 0.02+ , medicareLevyThresholdIndividual = Money 21980+ , medicareLevyThresholdIndividualSeniorAndPensioner = Money 34758+ , medicareLevyThresholdFamily = Money 37089+ , medicareLevyThresholdFamilySeniorAndPensioner = Money 48385+ , medicareLevyThresholdDependentChildIncrease = Money 3406+ }+ -- | Individual tax rates unchanged from 2017. -- -- The /temporary budget repair levy/ no longer applies.@@ -44,7 +53,7 @@ tables :: (Ord a, Fractional a) => TaxTables FY a tables = TaxTables FY2017.individualIncomeTax- (medicareLevy (review money 21980))+ medicare (ttMedicareLevySurcharge FY2017.tables) help sfss
src/Data/Tax/ATO/FY/FY2019.hs view
@@ -20,7 +20,6 @@ module Data.Tax.ATO.FY.FY2019 (FY, fyProxy, tables) where import Data.Proxy-import Control.Lens (review) import Data.Tax import Data.Tax.ATO.Common@@ -46,6 +45,16 @@ , (86856, 0.005), (91426, 0.005), (100614, 0.005), (107214, 0.005) ] sfss = thresholds' [(51957, 0.02), (64307, 0.01), (91426, 0.01)] +medicare :: (Fractional a) => MedicareLevyRatesAndThresholds a+medicare = MedicareLevyRatesAndThresholds+ { medicareLevyRate = 0.02+ , medicareLevyThresholdIndividual = Money 22398+ , medicareLevyThresholdIndividualSeniorAndPensioner = Money 35418+ , medicareLevyThresholdFamily = Money 37794+ , medicareLevyThresholdFamilySeniorAndPensioner = Money 49304+ , medicareLevyThresholdDependentChildIncrease = Money 3471+ }+ -- | The 37% threshold was increased from $87,000 to $90,000. -- -- The new /low and middle income tax offset (LAMITO)/ was@@ -54,7 +63,7 @@ tables :: (Ord a, Fractional a) => TaxTables FY a tables = TaxTables individualIncomeTax- (medicareLevy (review money 22398))+ medicare (ttMedicareLevySurcharge FY2018.tables) help sfss
src/Data/Tax/ATO/FY/FY2020.hs view
@@ -20,7 +20,6 @@ module Data.Tax.ATO.FY.FY2020 (FY, fyProxy, tables) where import Data.Proxy-import Control.Lens (review) import Data.Tax import Data.Tax.ATO.Common@@ -53,6 +52,16 @@ , (134573, 0.005) ] +medicare :: (Fractional a) => MedicareLevyRatesAndThresholds a+medicare = MedicareLevyRatesAndThresholds+ { medicareLevyRate = 0.02+ , medicareLevyThresholdIndividual = Money 22801+ , medicareLevyThresholdIndividualSeniorAndPensioner = Money 36056+ , medicareLevyThresholdFamily = Money 38474+ , medicareLevyThresholdFamilySeniorAndPensioner = Money 50191+ , medicareLevyThresholdDependentChildIncrease = Money 3533+ }+ -- | From 1 July 2019, all study and training loans are covered by -- one set of thresholds and rates. For backwards compatibility, -- 'ttHelp' and 'ttSfss' now refer to the same value.@@ -60,7 +69,7 @@ tables :: (Ord a, Fractional a) => TaxTables FY a tables = TaxTables (ttIndividualIncomeTax FY2019.tables)- (medicareLevy (review money 22801))+ medicare (ttMedicareLevySurcharge FY2019.tables) help help
src/Data/Tax/ATO/FY/FY2021.hs view
@@ -20,7 +20,6 @@ module Data.Tax.ATO.FY.FY2021 (FY, fyProxy, tables, individualIncomeTax) where import Data.Proxy-import Control.Lens (review) import Data.Tax import Data.Tax.ATO.Common@@ -63,10 +62,20 @@ , (136740, 0.005) ] +medicare :: (Fractional a) => MedicareLevyRatesAndThresholds a+medicare = MedicareLevyRatesAndThresholds+ { medicareLevyRate = 0.02+ , medicareLevyThresholdIndividual = Money 23226+ , medicareLevyThresholdIndividualSeniorAndPensioner = Money 36705+ , medicareLevyThresholdFamily = Money 39167+ , medicareLevyThresholdFamilySeniorAndPensioner = Money 51094+ , medicareLevyThresholdDependentChildIncrease = Money 3597+ }+ tables :: (Ord a, Fractional a) => TaxTables FY a tables = TaxTables individualIncomeTax- (medicareLevy (review money 23226))+ medicare (ttMedicareLevySurcharge FY2020.tables) help help
src/Data/Tax/ATO/FY/FY2022.hs view
@@ -20,7 +20,6 @@ module Data.Tax.ATO.FY.FY2022 (FY, fyProxy, tables) where import Data.Proxy-import Control.Lens (review) import Data.Tax import Data.Tax.ATO.Common@@ -53,10 +52,20 @@ , (137898, 0.005) ] +medicare :: (Fractional a) => MedicareLevyRatesAndThresholds a+medicare = MedicareLevyRatesAndThresholds+ { medicareLevyRate = 0.02+ , medicareLevyThresholdIndividual = Money 23365+ , medicareLevyThresholdIndividualSeniorAndPensioner = Money 36925+ , medicareLevyThresholdFamily = Money 39402+ , medicareLevyThresholdFamilySeniorAndPensioner = Money 51401+ , medicareLevyThresholdDependentChildIncrease = Money 3619+ }+ tables :: (Ord a, Fractional a) => TaxTables FY a tables = TaxTables FY2021.individualIncomeTax- (medicareLevy (review money 23365))+ medicare (ttMedicareLevySurcharge FY2021.tables) help help@@ -75,7 +84,7 @@ -- | LMITO ceiling increased by $420 to $1500 in FY2022 lmito2022 :: (Fractional a, Ord a) => Tax (Money a) (Money a) lmito2022 = limit mempty $- greaterOf (lump (review money (-1500)))- ( lump (review money (-255))- <> above (review money 37000) (-0.075) )- <> above (review money 90000) 0.03+ greaterOf (lump (Money (-1500)))+ ( lump (Money (-255))+ <> above (Money 37000) (-0.075) )+ <> above (Money 90000) 0.03
src/Data/Tax/ATO/FY/FY2023.hs view
@@ -50,11 +50,20 @@ , (141848, 0.005) ] +medicare :: (Fractional a) => MedicareLevyRatesAndThresholds a+medicare = MedicareLevyRatesAndThresholds+ { medicareLevyRate = 0.02+ , medicareLevyThresholdIndividual = Money 24276+ , medicareLevyThresholdIndividualSeniorAndPensioner = Money 38365+ , medicareLevyThresholdFamily = Money 40939+ , medicareLevyThresholdFamilySeniorAndPensioner = Money 53406+ , medicareLevyThresholdDependentChildIncrease = Money 3760+ }+ tables :: (Ord a, Fractional a) => TaxTables 2023 a tables = TaxTables (ttIndividualIncomeTax FY2022.tables)-- (medicareLevy (Money 24276))+ medicare (ttMedicareLevySurcharge FY2022.tables) help
src/Data/Tax/ATO/FY/FY2024.hs view
@@ -22,6 +22,7 @@ import Data.Proxy import Data.Tax import Data.Tax.ATO.Common+import Data.Tax.ATO.PrivateHealthInsuranceRebate import qualified Data.Tax.ATO.FY.FY2023 as FY2023 type FY = 2024@@ -50,6 +51,16 @@ , (151201, 0.005) ] +medicare :: (Fractional a) => MedicareLevyRatesAndThresholds a+medicare = MedicareLevyRatesAndThresholds+ { medicareLevyRate = 0.02+ , medicareLevyThresholdIndividual = Money 26000+ , medicareLevyThresholdIndividualSeniorAndPensioner = Money 41089+ , medicareLevyThresholdFamily = Money 43846+ , medicareLevyThresholdFamilySeniorAndPensioner = Money 57198+ , medicareLevyThresholdDependentChildIncrease = Money 4027+ }+ -- | Medicare levy surcharge thresholds changed for 2023–24 medicareLevySurcharge :: (Fractional a, Ord a) => Tax (Money a) (Money a) medicareLevySurcharge =@@ -57,18 +68,25 @@ <> threshold (Money 108000) 0.0025 <> threshold (Money 144000) 0.0025 +-- Rebate adjustment factor = 1.000 (no change)+-- https://www.health.gov.au/news/phi-circulars/phi-1724-private-health-insurance-rebate-adjustment-factor-effective-1-april-2024+-- However, the /thresholds/ did change this year.+privateHealthInsuranceRebateRates+ :: (Fractional a) => PrivateHealthInsuranceRebateRates a+privateHealthInsuranceRebateRates =+ [ ( 93000, (0.24608, 0.24608), (0.28710, 0.28710), (0.32812, 0.32812) )+ , (108000, (0.16405, 0.16405), (0.20507, 0.20507), (0.24608, 0.24608) )+ , (144000, (0.08202, 0.08202), (0.12303, 0.12303), (0.16405, 0.16405) )+ ]+ tables :: (Ord a, Fractional a) => TaxTables FY a tables = TaxTables (ttIndividualIncomeTax FY2023.tables)-- (medicareLevy (Money 26000))-+ medicare medicareLevySurcharge help help lowIncomeTaxOffset2021 - -- Rebate adjustment factor = 1.000 (no change)- -- https://www.health.gov.au/news/phi-circulars/phi-1724-private-health-insurance-rebate-adjustment-factor-effective-1-april-2024- (ttPHIRebateRates FY2023.tables)+ privateHealthInsuranceRebateRates
+ src/Data/Tax/ATO/FY/FY2025.hs view
@@ -0,0 +1,102 @@+-- This file is part of hs-tax-ato+-- Copyright (C) 2024 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/>.++{-# LANGUAGE DataKinds #-}++-- | Tax tables for 2024–25 financial year.+--+-- These data are NOT YET FINAL. We are waiting on federal budget+-- (25 March 2025) to confirm Medicare Levy thresholds, and the PHI+-- rebate adjustment factor (~1 April 2025).+module Data.Tax.ATO.FY.FY2025 (FY, fyProxy, tables) where++import Data.Proxy+import Data.Tax+import Data.Tax.ATO.Common+import Data.Tax.ATO.PrivateHealthInsuranceRebate++type FY = 2025+fyProxy :: Proxy FY+fyProxy = Proxy++help :: (Fractional a, Ord a) => Tax (Money a) (Money a)+help = thresholds'+ [ (54435, 0.01)+ , (62851, 0.01)+ , (66621, 0.005)+ , (70619, 0.005)+ , (74856, 0.005)+ , (79347, 0.005)+ , (84108, 0.005)+ , (89155, 0.005)+ , (94504, 0.005)+ , (100175, 0.005)+ , (106186, 0.005)+ , (122557, 0.005)+ , (119310, 0.005)+ , (126468, 0.005)+ , (134057, 0.005)+ , (142101, 0.005)+ , (150627, 0.005)+ , (159664, 0.005)+ ]++medicare :: (Fractional a) => MedicareLevyRatesAndThresholds a+medicare = MedicareLevyRatesAndThresholds+ { medicareLevyRate = 0.02+ , medicareLevyThresholdIndividual = Money 27222+ , medicareLevyThresholdIndividualSeniorAndPensioner = Money 43020+ , medicareLevyThresholdFamily = Money 45907+ , medicareLevyThresholdFamilySeniorAndPensioner = Money 59886+ , medicareLevyThresholdDependentChildIncrease = Money 4216+ }++-- | Medicare levy surcharge thresholds changed for 2024–25+medicareLevySurcharge :: (Fractional a, Ord a) => Tax (Money a) (Money a)+medicareLevySurcharge =+ threshold (Money 97000) 0.01+ <> threshold (Money 113000) 0.0025+ <> threshold (Money 151000) 0.0025++-- | In 2024–25 the "stage three tax cuts" came into effect.+individualIncomeTax :: (Fractional a, Ord a) => Tax (Money a) (Money a)+individualIncomeTax = marginal'+ [ (18200, 0.16)+ , (45000, 0.30 - 0.16)+ , (135000, 0.37 - 0.30)+ , (190000, 0.45 - 0.37) ]++-- Rebate adjustment factor = TBC (currently re-using FY2024 rates)+-- However, the /thresholds/ did change this year.+privateHealthInsuranceRebateRates+ :: (Fractional a) => PrivateHealthInsuranceRebateRates a+privateHealthInsuranceRebateRates =+ [ ( 97000, (0.24608, 0.24288), (0.28710, 0.28337), (0.32812, 0.32385) )+ , (113000, (0.16405, 0.16192), (0.20507, 0.20240), (0.24608, 0.24288) )+ , (151000, (0.08202, 0.08095), (0.12303, 0.12143), (0.16405, 0.16192) )+ ]++tables :: (Ord a, Fractional a) => TaxTables FY a+tables = TaxTables+ individualIncomeTax+ medicare+ medicareLevySurcharge+ help+ help++ lowIncomeTaxOffset2021++ privateHealthInsuranceRebateRates
+ src/Data/Tax/ATO/PaymentSummary.hs view
@@ -0,0 +1,646 @@+-- This file is part of hs-tax-ato+-- Copyright (C) 2025 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/>.++{-# LANGUAGE PatternSynonyms #-}++{-|++Types and optics for payment summaries.++-}+module Data.Tax.ATO.PaymentSummary+ (+ -- ** Individual non-business+ PaymentSummaryIndividualNonBusiness+ , newPaymentSummaryIndividualNonBusiness+ , GrossPaymentsTypeIndividualNonBusiness(..)+ , grossPaymentsTypeP+ , grossPaymentsTypeH++ -- *** Allowances+ , allowances+ , Allowance+ , allowance+ , allowanceDetail+ , allowanceAmount++ -- *** Fringe benefits+ , HasReportableFringeBenefits(..)+ , fringeBenefitsEmployerNotExempt+ , fringeBenefitsEmployerExempt+ , ReportableFringeBenefits(..)+ , FBTEmployerExemption(..)++ -- *** Lump sum A+ , HasLumpSumA(..)+ , lumpSumATypeR+ , lumpSumATypeT+ , LumpSumA+ , lumpSumAType+ , lumpSumAAmount+ , LumpSumAType(..)++ -- *** Lump sum B+ , lumpSumB++ -- *** Lump sum D+ , HasLumpSumD(..)++ -- *** Lump sum E+ , HasLumpSumE(..)++ -- *** Exempt foreign employment income+ , exemptForeignEmploymentIncome++ -- ** Foreign employment+ , PaymentSummaryForeignEmployment+ , newPaymentSummaryForeignEmployment+ , GrossPaymentsTypeForeignEmployment(..)+ , foreignTaxPaid++ -- ** Business and personal services income+ , PaymentSummaryBusinessAndPersonalServicesIncome+ , newPaymentSummaryBusinessAndPersonalServicesIncome++ -- ** Withholding where ABN not quoted+ , PaymentSummaryWithholdingWhereABNNotQuoted+ , newPaymentSummaryWithholdingWhereABNNotQuoted++ -- ** Payer details+ , PayerDetails+ , newPayerDetails+ , payerABN+ , payerBranchNumber+ , payerName+ , HasPayerDetails(..)++ -- ** Classes and helpers+ , HasGrossPayments(..)+ , HasGrossPaymentsType(..)+ , HasTotalTaxWithheld(..)+ , HasReportableEmployerSuperannuationContributions(..)+ , pattern PaymentSummary+ )+ where++import Data.String (IsString(..))++import Control.Lens++import Data.Tax+import Data.Tax.ATO.ABN (ABN)+import Data.Tax.ATO.Common+import Data.Tax.ATO.Rounding+++-- | Deprecated pattern provided for compatibility. Will be removed+-- in a future release. Use 'PaymentSummaryIndividualNonBusiness'+-- constructor and accessors instead.+--+pattern PaymentSummary+ :: (Num a) => PayerDetails -> Money a -> Money a -> Money a -> PaymentSummaryIndividualNonBusiness a+pattern PaymentSummary payer gross tax resc <-+ PaymentSummaryIndividualNonBusiness payer tax gross _type resc _fb+ _allow _lumpA _lumpB _lumpD _lumpE _foreign+ where+ PaymentSummary payer gross tax resc = newPaymentSummaryIndividualNonBusiness payer+ & set grossPayments gross+ & set totalTaxWithheld tax+ & set reportableEmployerSuperannuationContributions resc+{-# DEPRECATED PaymentSummary "see instead PaymentSummaryIndividualNonBusiness" #-}+++-- | PAYG payment summary - individual non-business.+--+-- Use 'newPaymentSummaryIndividualNonBusiness' to construct this data+-- type (all amounts initially zero).+--+-- To @set@ and @view@ the various fields, these lenses are available:+--+-- +-------------------------------------------------+-----------------------------------------++-- | 'payerDetails' | Use 'newPayerDetails' to construct. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'totalTaxWithheld' | TOTAL TAX WITHHELD |+-- +-------------------------------------------------+-----------------------------------------++-- | 'grossPayments' | GROSS PAYMENTS. Do not include amounts |+-- | | shown at 'allowances', 'lumpSumA', |+-- | | 'lumpSumB', 'lumpSumD', 'lumpSumE', |+-- | | or 'exemptForeignEmploymentIncome'. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'grossPaymentsType' | Use 'grossPaymentsTypeP' for non super |+-- | | pensions and annuities, or |+-- | | 'grossPaymentsTypeH' for working |+-- | | holiday makers. Otherwise, leave unset. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'reportableEmployerSuperannuationContributions' | Reportable employer superannuation |+-- | | contributions (do not include |+-- | | compulsory super guarantee amounts) |+-- +-------------------------------------------------+-----------------------------------------++-- | 'reportableFringeBenefits' | Fringe benefits amount for FBT year |+-- | | 1 April to 31 March, and employer |+-- | | FBT exemption status. See also |+-- | | 'ReportableFringeBenefits'. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'exemptForeignEmploymentIncome' | |+-- +-------------------------------------------------+-----------------------------------------++-- | 'allowances' | List of 'allowance'. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'lumpSumA' | Lump sum A. Use 'lumpSumATypeR' or |+-- | | 'lumpSumATypeT' to construct. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'lumpSumB' | Lump sum B. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'lumpSumD' | Lump sum D. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'lumpSumE' | Lump sum E - payments in arrears. This |+-- | | amount is included in taxable income. |+-- | | The tax offset calculations are not yet |+-- | | implemented. |+-- +-------------------------------------------------+-----------------------------------------++--+data PaymentSummaryIndividualNonBusiness a = PaymentSummaryIndividualNonBusiness+ { _inbPayer :: PayerDetails+ , _inbWithholding :: Money a+ , _inbGross :: Money a+ , _inbGrossPaymentsType :: Maybe GrossPaymentsTypeIndividualNonBusiness+ , _inbRESC :: Money a+ , _inbFringeBenefits :: Maybe (ReportableFringeBenefits a)+ , _inbAllowances :: [Allowance a]+ , _inbLumpSumA :: Maybe (LumpSumA a)+ , _inbLumpSumB :: Money a+ , _inbLumpSumD :: Money a+ , _inbLumpSumE :: Money a+ , _inbForeign :: Money a+ }++-- | Construct a new payment summary. All amounts are initially zero.+newPaymentSummaryIndividualNonBusiness+ :: (Num a) => PayerDetails -> PaymentSummaryIndividualNonBusiness a+newPaymentSummaryIndividualNonBusiness payer =+ PaymentSummaryIndividualNonBusiness payer+ mempty -- total tax withheld+ mempty -- gross payments+ Nothing -- gross payments type+ mempty -- reportable super contributions+ Nothing -- reportable fringe benefits+ [] -- allowances+ Nothing -- lump sum a+ mempty -- lump sum b+ mempty -- lump sum d+ mempty -- lump sum e+ mempty -- exempt foreign employment income++data GrossPaymentsTypeIndividualNonBusiness+ = GrossPaymentsTypeP+ -- ^ non super pensions or annuity. See also 'grossPaymentsTypeP'.+ | GrossPaymentsTypeH+ -- ^ working holiday makers. See also 'grossPaymentsTypeH'.+ deriving (Eq, Ord)++-- | Helper constructor - __P - non super pensions or annuity__+grossPaymentsTypeP :: Maybe GrossPaymentsTypeIndividualNonBusiness+grossPaymentsTypeP = Just GrossPaymentsTypeP++-- | Helper constructor - __H - working holiday makers__+grossPaymentsTypeH :: Maybe GrossPaymentsTypeIndividualNonBusiness+grossPaymentsTypeH = Just GrossPaymentsTypeH++instance (RealFrac a) => HasTaxableIncome PaymentSummaryIndividualNonBusiness a a where+ taxableIncome = to $ \s ->+ view grossPayments s+ <> foldOf (allowances . traverse . allowanceAmount) s+ <> foldOf (lumpSumA . traverse . lumpSumAAmount) s+ <> view (lumpSumB . to (wholeDollars . ($/ 20))) s+ <> view lumpSumE s++instance HasTaxWithheld PaymentSummaryIndividualNonBusiness a a where+ taxWithheld = totalTaxWithheld++instance HasPayerDetails PaymentSummaryIndividualNonBusiness where+ payerDetails = lens _inbPayer (\s b -> s { _inbPayer = b })++instance HasTotalTaxWithheld PaymentSummaryIndividualNonBusiness where+ totalTaxWithheld = lens _inbWithholding (\s b -> s { _inbWithholding = b })++instance HasGrossPayments PaymentSummaryIndividualNonBusiness where+ grossPayments = lens _inbGross (\s b -> s { _inbGross = b })++instance HasGrossPaymentsType PaymentSummaryIndividualNonBusiness+ (Maybe GrossPaymentsTypeIndividualNonBusiness) where+ grossPaymentsType = lens _inbGrossPaymentsType (\s b -> s { _inbGrossPaymentsType = b })++instance HasReportableEmployerSuperannuationContributions PaymentSummaryIndividualNonBusiness where+ reportableEmployerSuperannuationContributions =+ lens _inbRESC (\s b -> s { _inbRESC = b })++instance HasReportableFringeBenefits PaymentSummaryIndividualNonBusiness where+ reportableFringeBenefits =+ lens _inbFringeBenefits (\s b -> s { _inbFringeBenefits = b })++instance HasLumpSumA PaymentSummaryIndividualNonBusiness where+ lumpSumA = lens _inbLumpSumA (\s b -> s { _inbLumpSumA = b })++lumpSumB :: Lens' (PaymentSummaryIndividualNonBusiness a) (Money a)+lumpSumB = lens _inbLumpSumB (\s b -> s { _inbLumpSumB = b })++instance HasLumpSumD PaymentSummaryIndividualNonBusiness where+ lumpSumD = lens _inbLumpSumD (\s b -> s { _inbLumpSumD = b })++instance HasLumpSumE PaymentSummaryIndividualNonBusiness where+ lumpSumE = lens _inbLumpSumE (\s b -> s { _inbLumpSumE = b })++exemptForeignEmploymentIncome :: Lens' (PaymentSummaryIndividualNonBusiness a) (Money a)+exemptForeignEmploymentIncome = lens _inbForeign (\s b -> s { _inbForeign = b })++allowances :: Lens' (PaymentSummaryIndividualNonBusiness a) [Allowance a]+allowances = lens _inbAllowances (\s b -> s { _inbAllowances = b })+++-- | PAYG payment summary - foreign employment+--+-- Use 'newPaymentSummaryForeignEmployment' to construct this data+-- type (all amounts initially zero).+--+-- To @set@ and @view@ the various fields, these lenses are available:+--+-- +-------------------------------------------------+-----------------------------------------++-- | 'payerDetails' | Use 'newPayerDetails' to construct. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'totalTaxWithheld' | TOTAL TAX WITHHELD |+-- +-------------------------------------------------+-----------------------------------------++-- | 'grossPayments' | GROSS PAYMENTS. You __must__ include |+-- | | allowances. Do not include 'lumpSumA' |+-- | | 'lumpSumD' or 'lumpSumE' amounts. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'grossPaymentsType' | Initial value 'GrossPaymentsTypeF'. |+-- | | @set@ to 'GrossPaymentsTypeJ' for income|+-- | | earned from work conducted in the Joint |+-- | | Petroleum Development Area (JPDA). |+-- +-------------------------------------------------+-----------------------------------------++-- | 'foreignTaxPaid' | |+-- +-------------------------------------------------+-----------------------------------------++-- | 'reportableEmployerSuperannuationContributions' | Reportable employer superannuation |+-- | | contributions (do not include |+-- | | compulsory super guarantee amounts) |+-- +-------------------------------------------------+-----------------------------------------++-- | 'reportableFringeBenefits' | Fringe benefits amount for FBT year |+-- | | 1 April to 31 March, and employer |+-- | | FBT exemption status. See also |+-- | | 'ReportableFringeBenefits'. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'lumpSumA' | Lump sum A. Use 'lumpSumATypeR' or |+-- | | 'lumpSumATypeT' to construct. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'lumpSumD' | Lump sum D. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'lumpSumE' | Lump sum E - payments in arrears. This |+-- | | amount is included in taxable income. |+-- | | The tax offset calculations are not yet |+-- | | implemented. |+-- +-------------------------------------------------+-----------------------------------------++--+data PaymentSummaryForeignEmployment a = PaymentSummaryForeignEmployment+ { _foreignPayer :: PayerDetails+ , _foreignWithholding :: Money a+ , _foreignGross :: Money a+ , _foreignGrossPaymentsType :: GrossPaymentsTypeForeignEmployment+ , _foreignForeignTaxPaid :: Money a+ , _foreignRESC :: Money a+ , _foreignFringeBenefits :: Maybe (ReportableFringeBenefits a)+ , _foreignLumpSumA :: Maybe (LumpSumA a)+ , _foreignLumpSumD :: Money a+ , _foreignLumpSumE :: Money a+ }++-- | Construct a new payment summary. All amounts are initially zero.+newPaymentSummaryForeignEmployment+ :: (Num a) => PayerDetails -> PaymentSummaryForeignEmployment a+newPaymentSummaryForeignEmployment payer =+ PaymentSummaryForeignEmployment payer+ mempty -- total tax withheld+ mempty -- gross payments+ GrossPaymentsTypeF -- gross payments type+ mempty -- foreign tax paid+ mempty -- reportable super contributions+ Nothing -- reportable fringe benefits+ Nothing -- lump sum a+ mempty -- lump sum d+ mempty -- lump sum e++data GrossPaymentsTypeForeignEmployment+ = GrossPaymentsTypeF+ -- ^ foreign employment income+ | GrossPaymentsTypeJ+ -- ^ income earned from work conducted in the Joint Petroleum+ -- Development Area (JPDA).+ deriving (Eq, Ord)++instance (RealFrac a) => HasTaxableIncome PaymentSummaryForeignEmployment a a where+ taxableIncome = to $ \s ->+ view grossPayments s+ <> foldOf (lumpSumA . traverse . lumpSumAAmount) s+ <> view lumpSumE s++instance HasTaxWithheld PaymentSummaryForeignEmployment a a where+ taxWithheld = totalTaxWithheld++instance HasPayerDetails PaymentSummaryForeignEmployment where+ payerDetails = lens _foreignPayer (\s b -> s { _foreignPayer = b })++instance HasTotalTaxWithheld PaymentSummaryForeignEmployment where+ totalTaxWithheld = lens _foreignWithholding (\s b -> s { _foreignWithholding = b })++instance HasGrossPayments PaymentSummaryForeignEmployment where+ grossPayments = lens _foreignGross (\s b -> s { _foreignGross = b })++instance HasGrossPaymentsType PaymentSummaryForeignEmployment+ GrossPaymentsTypeForeignEmployment where+ grossPaymentsType = lens _foreignGrossPaymentsType (\s b -> s { _foreignGrossPaymentsType = b })++foreignTaxPaid :: Lens' (PaymentSummaryForeignEmployment a) (Money a)+foreignTaxPaid =+ lens _foreignForeignTaxPaid (\s b -> s { _foreignForeignTaxPaid = b })++instance HasReportableEmployerSuperannuationContributions PaymentSummaryForeignEmployment where+ reportableEmployerSuperannuationContributions =+ lens _foreignRESC (\s b -> s { _foreignRESC = b })++instance HasReportableFringeBenefits PaymentSummaryForeignEmployment where+ reportableFringeBenefits =+ lens _foreignFringeBenefits (\s b -> s { _foreignFringeBenefits = b })++instance HasLumpSumA PaymentSummaryForeignEmployment where+ lumpSumA = lens _foreignLumpSumA (\s b -> s { _foreignLumpSumA = b })++instance HasLumpSumD PaymentSummaryForeignEmployment where+ lumpSumD = lens _foreignLumpSumD (\s b -> s { _foreignLumpSumD = b })++instance HasLumpSumE PaymentSummaryForeignEmployment where+ lumpSumE = lens _foreignLumpSumE (\s b -> s { _foreignLumpSumE = b })+++-- | PAYG payment summary - business and personal services income+--+-- Use 'newPaymentSummaryBusinessAndPersonalServicesIncome' to construct this data+-- type (all amounts initially zero).+--+-- To @set@ and @view@ the various fields, these lenses are available:+--+-- +-------------------------------------------------+-----------------------------------------++-- | 'payerDetails' | Use 'newPayerDetails' to construct. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'totalTaxWithheld' | TOTAL TAX WITHHELD |+-- +-------------------------------------------------+-----------------------------------------++-- | 'grossPayments' | Gross payments or gross attributed |+-- | | income. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'reportableEmployerSuperannuationContributions' | Reportable employer superannuation |+-- | | contributions (do not include |+-- | | compulsory super guarantee amounts) |+-- +-------------------------------------------------+-----------------------------------------++--+data PaymentSummaryBusinessAndPersonalServicesIncome a = PaymentSummaryBusinessAndPersonalServicesIncome+ { _bpsiPayer :: PayerDetails+ , _bpsiWithholding :: Money a+ , _bpsiGross :: Money a+ , _bpsiRESC :: Money a+ }++-- | Construct a new payment summary. All amounts are initially zero.+newPaymentSummaryBusinessAndPersonalServicesIncome+ :: (Num a) => PayerDetails -> PaymentSummaryBusinessAndPersonalServicesIncome a+newPaymentSummaryBusinessAndPersonalServicesIncome payer =+ PaymentSummaryBusinessAndPersonalServicesIncome payer+ mempty -- total tax withheld+ mempty -- gross payments+ mempty -- reportable super contributions++instance HasTaxableIncome PaymentSummaryBusinessAndPersonalServicesIncome a a where+ taxableIncome = grossPayments++instance HasTaxWithheld PaymentSummaryBusinessAndPersonalServicesIncome a a where+ taxWithheld = totalTaxWithheld++instance HasPayerDetails PaymentSummaryBusinessAndPersonalServicesIncome where+ payerDetails = lens _bpsiPayer (\s b -> s { _bpsiPayer = b })++instance HasTotalTaxWithheld PaymentSummaryBusinessAndPersonalServicesIncome where+ totalTaxWithheld = lens _bpsiWithholding (\s b -> s { _bpsiWithholding = b })++instance HasGrossPayments PaymentSummaryBusinessAndPersonalServicesIncome where+ grossPayments = lens _bpsiGross (\s b -> s { _bpsiGross = b })++instance HasReportableEmployerSuperannuationContributions PaymentSummaryBusinessAndPersonalServicesIncome where+ reportableEmployerSuperannuationContributions =+ lens _bpsiRESC (\s b -> s { _bpsiRESC = b })+++-- | PAYG payment summary - withholding where ABN not quoted (other+-- than those covered by annual investment income reporting).+--+-- Use 'newPaymentSummaryWithholdingWhereABNNotQuoted' to construct this data+-- type (all amounts initially zero).+--+-- To @set@ and @view@ the various fields, these lenses are available:+--+-- +-------------------------------------------------+-----------------------------------------++-- | 'payerDetails' | Use 'newPayerDetails' to construct. |+-- +-------------------------------------------------+-----------------------------------------++-- | 'totalTaxWithheld' | TOTAL AMOUNT WITHHELD |+-- +-------------------------------------------------+-----------------------------------------++-- | 'grossPayments' | Gross payment (including the market |+-- | | value of non-cash benefits). |+-- +-------------------------------------------------+-----------------------------------------++--+data PaymentSummaryWithholdingWhereABNNotQuoted a = PaymentSummaryWithholdingWhereABNNotQuoted+ { _noabnPayer :: PayerDetails+ , _noabnWithholding :: Money a+ , _noabnGross :: Money a+ }++-- | Construct a new payment summary. All amounts are initially zero.+newPaymentSummaryWithholdingWhereABNNotQuoted+ :: (Num a) => PayerDetails -> PaymentSummaryWithholdingWhereABNNotQuoted a+newPaymentSummaryWithholdingWhereABNNotQuoted payer =+ PaymentSummaryWithholdingWhereABNNotQuoted payer+ mempty -- total tax withheld+ mempty -- gross payments++instance HasTaxableIncome PaymentSummaryWithholdingWhereABNNotQuoted a a where+ taxableIncome = grossPayments++instance HasTaxWithheld PaymentSummaryWithholdingWhereABNNotQuoted a a where+ taxWithheld = totalTaxWithheld++instance HasPayerDetails PaymentSummaryWithholdingWhereABNNotQuoted where+ payerDetails = lens _noabnPayer (\s b -> s { _noabnPayer = b })++instance HasTotalTaxWithheld PaymentSummaryWithholdingWhereABNNotQuoted where+ totalTaxWithheld = lens _noabnWithholding (\s b -> s { _noabnWithholding = b })++instance HasGrossPayments PaymentSummaryWithholdingWhereABNNotQuoted where+ grossPayments = lens _noabnGross (\s b -> s { _noabnGross = b })+++-- | Objects which have a /GROSS PAYMENTS/ field.+class HasGrossPayments s where+ grossPayments :: Lens' (s a) (Money a)++-- | Objects which have a /gross payments type/ field.+-- The value type may vary.+--+class HasGrossPaymentsType s a where+ grossPaymentsType :: Lens' (s any) a++-- | Objects which have a /GROSS PAYMENTS/ field.+class HasTotalTaxWithheld s where+ totalTaxWithheld :: Lens' (s a) (Money a)++-- | Objects which may have Reportable employer superannuation contributions+class HasReportableEmployerSuperannuationContributions s where+ reportableEmployerSuperannuationContributions :: Lens' (s a) (Money a)+++-- | Objects which may have reportable fringe benefit amounts+class HasReportableFringeBenefits s where+ reportableFringeBenefits :: Lens' (s a) (Maybe (ReportableFringeBenefits a))++-- | Helper constructor for fringe benefits amount (employer not exempt from FBT).+-- See also 'fringeBenefitsEmployerExempt'.+fringeBenefitsEmployerNotExempt :: Money a -> Maybe (ReportableFringeBenefits a)+fringeBenefitsEmployerNotExempt x = Just $ ReportableFringeBenefits x EmployerNotFBTExempt++-- | Helper constructor for fringe benefits amount (employer exempt from FBT)+-- See also 'fringeBenefitsEmployerNotExempt'.+fringeBenefitsEmployerExempt :: Money a -> Maybe (ReportableFringeBenefits a)+fringeBenefitsEmployerExempt x = Just $ ReportableFringeBenefits x EmployerFBTExempt++data FBTEmployerExemption = EmployerNotFBTExempt | EmployerFBTExempt+ deriving (Eq, Ord)++-- | Reportable fringe benefits amount, with the employer exemption status.+--+-- For setting the fringe benefits amount in a+-- 'PaymentSummaryIndividualNonBusiness', we provide more ergonomic helper+-- constructors: 'fringeBenefitsEmployerNotExempt' and+-- 'fringeBenefitsEmployerExempt'.+--+data ReportableFringeBenefits a =+ ReportableFringeBenefits (Money a) FBTEmployerExemption+ deriving (Eq, Ord)+++-- | Use 'allowance' to construct, and lenses 'allowanceDetail' and+-- 'allowanceAmount' for field access.+--+data Allowance a = Allowance+ { _allowanceDetail :: String+ , _allowanceAmount :: (Money a)+ }+ deriving (Eq, Ord)++allowance+ :: (RealFrac a)+ => String -- ^ Allowance details+ -> Money a -- ^ Amount (discards cents)+ -> Allowance a+allowance s = Allowance s . wholeDollars++allowanceDetail :: Lens' (Allowance a) String+allowanceDetail = lens _allowanceDetail (\s b -> s { _allowanceDetail = b })++allowanceAmount :: Lens (Allowance a) (Allowance b) (Money a) (Money b)+allowanceAmount = lens _allowanceAmount (\s b -> s { _allowanceAmount = b })+++-- | Use 'lumpSumATypeR' or 'lumpSumATypeT' to construct, and lenses+-- 'lumpSumAType' and 'lumpSumAAmount' for field access.+data LumpSumA a = LumpSumA+ { _lumpSumAType :: LumpSumAType+ , _lumpSumAAmount :: Money a+ }+ deriving (Eq, Ord)++data LumpSumAType+ = LumpSumATypeR+ -- ^ if the payment was made for a genuine redundancy, invalidity+ -- or under an early retirement scheme+ | LumpSumATypeT+ -- ^ if the payment was made for any other reason+ deriving (Eq, Ord)++-- | A /lump sum A/ payment made for genuine redundancy, invalidity+-- or under an early retirement scheme. See also 'lumpSumATypeT'.+lumpSumATypeR :: (RealFrac a) => Money a -> LumpSumA a+lumpSumATypeR = LumpSumA LumpSumATypeR . wholeDollars++-- | A /lump sum A/ payment made for any other reason.+-- See also 'lumpSumATypeR'.+lumpSumATypeT :: (RealFrac a) => Money a -> LumpSumA a+lumpSumATypeT = LumpSumA LumpSumATypeT . wholeDollars++lumpSumAType :: Lens' (LumpSumA a) LumpSumAType+lumpSumAType = lens _lumpSumAType (\s b -> s { _lumpSumAType = b })++lumpSumAAmount :: Lens (LumpSumA a) (LumpSumA b) (Money a) (Money b)+lumpSumAAmount = lens _lumpSumAAmount (\s b -> s { _lumpSumAAmount = b })++class HasLumpSumA s where+ lumpSumA :: Lens' (s a) (Maybe (LumpSumA a))+++class HasLumpSumD s where+ lumpSumD :: Lens' (s a) (Money a)+++class HasLumpSumE s where+ lumpSumE :: Lens' (s a) (Money a)+++-- | Payer details. Use 'newPayerDetails' to construct.+-- Use 'payerABN', 'payerBranchNumber' and 'payerName' lenses to view or+-- set the fields.+--+-- Use the 'payerDetails' classy optic to access the payer details field+-- in payment summary data types.+--+data PayerDetails = PayerDetails+ { _payerABN :: ABN+ , _payerBranch :: Maybe Int+ , _payerName :: String+ }+ deriving (Eq, Ord)++-- | __Deprecated__ instance that interprets string as ABN and+-- sets payer name to the empty string.+--+instance IsString PayerDetails where+ fromString s = PayerDetails (fromString s) Nothing ""++newPayerDetails :: ABN -> Maybe Int -> String -> PayerDetails+newPayerDetails = PayerDetails++payerABN :: Lens' PayerDetails ABN+payerABN = lens _payerABN (\s b -> s { _payerABN = b })++payerBranchNumber :: Lens' PayerDetails (Maybe Int)+payerBranchNumber = lens _payerBranch (\s b -> s { _payerBranch = b })++payerName :: Lens' PayerDetails String+payerName = lens _payerName (\s b -> s { _payerName = b })++class HasPayerDetails s where+ payerDetails :: Lens' (s a) PayerDetails
src/Data/Tax/ATO/Pretty.hs view
@@ -27,13 +27,12 @@ module Data.Tax.ATO.Pretty ( summariseTaxReturnInfo , summariseAssessment- , summariseCGTAssessment+ , formatMoney ) where -import Data.Function (on)-import Data.List (groupBy, sortOn)+import Data.List.NonEmpty as NE (NonEmpty, groupAllWith, head) -import Control.Lens (ALens', cloneLens, view, views)+import Control.Lens (ALens', cloneLens, foldOf, view, views) import qualified Text.PrettyPrint as P import Data.Tax.ATO@@ -62,6 +61,11 @@ twoCol :: (P.Doc, Money Rational) -> P.Doc twoCol (label, value) = label P.$$ P.nest (80 - colWidthMoney) (formatMoney value) +omitIfZero :: ((a, Money Rational) -> P.Doc) -> (a, Money Rational) -> P.Doc+omitIfZero f rec@(_,x)+ | x == mempty = P.empty+ | otherwise = f rec+ threeCol :: (P.Doc, Money Rational, Money Rational) -> P.Doc threeCol (label, v1, v2) = label@@ -81,14 +85,18 @@ summariseTaxReturnInfo info = "Income" P.$+$ vcatWith threeCol- [ (" 1 Salary or wages" , view (paymentSummaries . taxWithheld) info, view (paymentSummaries . taxableIncome) info)+ [ ( " 1 Salary or wages"+ , view (paymentSummariesIndividualNonBusiness . taxWithheld) info+ , view (paymentSummariesIndividualNonBusiness . taxableIncome) info+ ) , (" 10 Interest" , view (interest . taxWithheld) info, view (interest . taxableIncome) info) ] P.$+$ " 11 Dividends" P.$+$ views dividends summariseDividends info+ P.$+$ views ess summariseESS info+ P.$+$ summariseCGT info P.$+$ vcatWith twoCol- [ (" 12 Employee share schemes" , view (ess . taxableIncome) info)- , (" 20M Other net foreign source income" , view foreignIncome info)+ [ (" 20M Other net foreign source income" , view foreignIncome info) ] P.$+$ "Deductions" P.$+$ P.vcat (uncurry (summariseDeduction (view deductions info)) <$> deductionsTable)@@ -100,16 +108,50 @@ summariseDividends :: [Dividend Rational] -> P.Doc summariseDividends = vcatWith (threeCol . prep)- . groupBy ((==) `on` dividendSource)- . sortOn dividendSource+ . groupAllWith dividendSource where- prep :: [Dividend Rational] -> (P.Doc, Money Rational, Money Rational)+ prep :: NonEmpty (Dividend Rational) -> (P.Doc, Money Rational, Money Rational) prep l =- ( P.text (" " <> dividendSource (head l))+ ( P.text (" " <> dividendSource (NE.head l)) , view taxWithheld l , view taxableIncome l ) +summariseESS :: [ESSStatement Rational] -> P.Doc+summariseESS [] = P.empty+summariseESS l =+ " 12 Employee share schemes"+ P.$+$ P.vcat+ [ twoCol+ ( " D Discount from upfront schemes - eligible for reduction"+ , foldOf (traverse . essTaxedUpfrontReduction) l )+ , twoCol+ ( " E Discount from upfront schemes - ineligible for reduction"+ , foldOf (traverse . essTaxedUpfrontNoReduction) l )+ , twoCol+ ( " F Discount from deferral schemes"+ , foldOf (traverse . essDeferral) l )+ , threeColLeft+ ( " C TFN amounts withheld from discounts"+ , foldOf (traverse . essTFNAmounts) l )+ , twoCol+ ( " A Foreign source discounts"+ , foldOf (traverse . essForeignSourceDiscounts) l )+ ]++summariseCGT :: TaxReturnInfo y Rational -> P.Doc+summariseCGT info+ | o == nullCGTAssessment = P.empty+ | otherwise =+ " 18 Capital gains"+ P.$+$ P.vcat+ [ twoCol (" A Net capital gain", view cgtNetGain o)+ , threeColLeft (" H Total current year capital gains", view cgtTotalCurrentYearGains o)+ , threeColLeft (" V Net capital losses carried forward", view cgtNetLossesCarriedForward o)+ ]+ where+ o = assessCGTEvents (view capitalLossCarryForward info) (view cgtEvents info)+ deductionsTable :: [(ALens' (Deductions Rational) (Money Rational), String)] deductionsTable = [ (workRelatedCarExpenses, "D1 Work-related car expenses")@@ -135,33 +177,34 @@ -> String -> P.Doc summariseDeduction a l desc- | amt > mempty- = P.nest 2 (P.text desc) P.$$ P.nest colWidthLabel (formatMoney amt)- | otherwise- = P.empty- where- amt = view (cloneLens l) a+ = omitIfZero twoCol (P.nest 2 (P.text desc), view (cloneLens l) a) summariseAssessment :: TaxAssessment Rational -> P.Doc summariseAssessment assessment = "Your taxable income is $" P.<> formatMoney (view taxableIncome assessment) P.$+$ P.text (replicate 80 '-')- P.$+$ vcatWith twoCol- [ ("Tax on your taxable income" , view taxDue assessment)- , ("Less credits and offsets" , views taxCreditsAndOffsets (fmap negate) assessment)- , ("Medicare levy (and surcharge, if any)" , view medicareLevyDue assessment)- , ("Study and training loan repayment" , view studyAndTrainingLoanRepayment assessment)- , ("Excess private health reduction or refund" , view privateHealthInsuranceRebateAdjustment assessment)- , ("Less PAYG withholding" , views taxWithheld (fmap negate) assessment)- , ("Less PAYG instalments" , views paygInstalmentsCredit (fmap negate) assessment)+ P.$+$ threeColLeft ("Tax on your taxable on net income" , view taxDue assessment)+ P.$+$ "Less non-refundable tax offsets"+ P.$+$ vcatWith (omitIfZero twoCol)+ [ (" Offset for super contributions on behalf of your spouse"+ , view offsetForSuperannuationContributionsOnBehalfOfYourSpouse assessment )+ , (" Foreign income tax offsets" , view foreignIncomeTaxOffsets assessment) ]+ P.$+$ "Less refundable tax offsets"+ P.$+$ twoCol (" Franking credit offset" , view frankingCreditOffset assessment)+ P.$+$ "Plus other liabilities"+ P.$+$ vcatWith (omitIfZero threeColLeft)+ [ (" Medicare levy" , view medicareLevyDue assessment)+ , (" Medicare levy surcharge" , view medicareLevySurchargeDue assessment)+ , (" Study and training loan repayment" , view studyAndTrainingLoanRepayment assessment)+ , (" Excess private health reduction or refund" , view privateHealthInsuranceRebateAdjustment assessment)+ ]+ P.$+$ "Less Pay as you go (PAYG) credits and other entitlements"+ P.$+$ vcatWith (omitIfZero twoCol)+ [ (" PAYG instalments" , view paygInstalmentsCredit assessment)+ , (" PAYG withholding" , view taxWithheld assessment)+ ] P.$+$ P.text (replicate 80 '-') P.$+$ "Result of this notice" P.$$ P.nest colWidthLabel (views taxBalance formatMoney assessment) P.$+$ "Net capital loss to carry forward" P.$$ P.nest colWidthLabel (views (taxCGTAssessment . capitalLossCarryForward) formatMoney assessment)--summariseCGTAssessment :: CGTAssessment Rational -> P.Doc-summariseCGTAssessment cgtAss@(CGTAssessment total _) =- "Total FY capital gains" P.$$ (P.nest colWidthLabel . formatMoney) total- P.$+$ "Net capital gain" P.$$ P.nest colWidthLabel (views cgtNetGain formatMoney cgtAss)- P.$+$ "Net capital loss to carry forward" P.$$ P.nest colWidthLabel (views capitalLossCarryForward formatMoney cgtAss)
src/Data/Tax/ATO/PrivateHealthInsuranceRebate.hs view
@@ -14,8 +14,6 @@ -- 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/>. -{-# LANGUAGE RankNTypes #-}- {- | Types and functions for the Private Health Insurance Rebate.
+ src/Data/Tax/ATO/TFN.hs view
@@ -0,0 +1,94 @@+-- This file is part of hs-tax-ato+-- Copyright (C) 2025 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/>.++{-|++Tax File Number (TFN) types and functions.++@+import qualified Data.Tax.ATO.TFN as TFN++main = do+ let+ tfnStr = "330 600 376"+ Just tfn = TFN.parse tfnStr+ tfnInt = TFN.asInt tfn+ Just tfn' = TFN.fromInt tfnInt+ putStrLn $ TFN.asString tfn' -- prints "330 600 376"+@++It is recommended to import this module qualified.++You can use the @OverloadedStrings@ language extension or the 'parse' function+to convert string to TFNs. Space characters are ignored, but other non-digits+will cause parse failure.++-}++module Data.Tax.ATO.TFN+ (+ TFN+ , parse+ , fromInt+ , asString+ , asInt+ ) where++import Data.Char (isDigit)+import Data.String+import Data.Maybe (fromJust)++-- | Tax File Number (TFN)+newtype TFN = TFN Int+ deriving (Eq, Ord, Show)++-- | Parse a TFN, throwing an error if it is not valid.+instance IsString TFN where+ fromString = fromJust . parse++-- | Construct a TFN, checking validity.+fromInt :: Int -> Maybe TFN+fromInt n | valid n = Just (TFN n)+fromInt _ = Nothing++-- | Parse a TFN. Spaces characters are allowed, other non-digit+-- characters are not.+parse :: String -> Maybe TFN+parse s+ | all isDigit s' = fromInt (read s')+ | otherwise = Nothing+ where s' = filter (/= ' ') s++valid :: Int -> Bool+valid n =+ (== 0) . (`mod` 11) . snd $ foldr step (n, 0) weights+ where+ weights = [1,4,3,7,5,8,6,9,10]+ step weight (n',acc) = ((+ acc) . (* weight)) <$> divMod n' 10++asInt :: TFN -> Int+asInt (TFN n) = n++-- Format TFN in the standard way (XXX XXX XXX)+asString :: TFN -> String+asString (TFN n) =+ case s' of+ [a1,a2,a3,b1,b2,b3,c1,c2,c3] -> [a1,a2,a3,' ',b1,b2,b3,' ',c1,c2,c3]+ _ -> show n -- can't happen, but just in case...+ where+ n' = abs n -- negative can't happen, but just in case...+ s = show n'+ s' = replicate (9 - length s) '0' <> s -- left-pad to 9 digits
tax-ato.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: tax-ato-version: 2024.1.0.1+version: 2025.1 synopsis: Tax types and computations for Australia description: This library provides types and tax computations for tax@@ -14,7 +14,7 @@ copyright: Copyright (C) 2018-2023 Fraser Tweedale category: Finance build-type: Simple-tested-with: GHC ==9.2.8 || ==9.4.7 || ==9.6.3 || ==9.8.1+tested-with: GHC ==9.6.7 || ==9.8.4 || ==9.10.2 || ==9.12.2 extra-source-files: .hlint.yaml extra-doc-files:@@ -27,7 +27,7 @@ location: https://github.com/frasertweedale/hs-tax-ato.git common common- default-language: Haskell2010+ default-language: GHC2021 ghc-options: -Wall -Wcompat@@ -41,18 +41,12 @@ -Wredundant-constraints -Wunused-packages -fhide-source-paths- if impl(ghc >= 9.0)- ghc-options:- -Winvalid-haddock- -Werror=unicode-bidirectional-format-characters- if impl(ghc >= 9.2)- ghc-options:- -Wimplicit-lift- -Woperator-whitespace- -Wredundant-bang-patterns- if impl(ghc >= 9.4)- ghc-options:- -Wredundant-strictness-flags+ -Winvalid-haddock+ -Werror=unicode-bidirectional-format-characters+ -Wimplicit-lift+ -Woperator-whitespace+ -Wredundant-bang-patterns+ -Wredundant-strictness-flags build-depends: base >= 4.14 && < 5 @@ -61,8 +55,12 @@ hs-source-dirs: src exposed-modules: Data.Tax.ATO+ Data.Tax.ATO.ABN+ Data.Tax.ATO.TFN Data.Tax.ATO.CGT Data.Tax.ATO.Common+ Data.Tax.ATO.Depreciation+ Data.Tax.ATO.PaymentSummary Data.Tax.ATO.Pretty Data.Tax.ATO.PrivateHealthInsuranceRebate Data.Tax.ATO.Rounding@@ -75,8 +73,9 @@ Data.Tax.ATO.FY.FY2022 Data.Tax.ATO.FY.FY2023 Data.Tax.ATO.FY.FY2024+ Data.Tax.ATO.FY.FY2025 build-depends:- , lens >= 4.12 && < 6- , time >= 1.11 && < 1.13+ , lens >= 4.18 && < 6+ , time >= 1.11 && < 1.15 , tax >= 0.2 && < 0.3 , pretty >= 1.1.3.6 && < 2