national-australia-bank-0.0.11: src/Data/Bank/NationalAustraliaBank/Report.hs
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE LambdaCase #-}
module Data.Bank.NationalAustraliaBank.Report(
cumulativeSumTransactions
, cumulativeDays
, cumulativeDays'
, cumulativePerDay
, cumulativePerDay'
) where
import Control.Lens ( view, over, Field1(_1), Field2(_2) )
import Data.Bank.NationalAustraliaBank.Transaction
( Transaction,
Amount,
Date,
diffDates,
realAmount,
date',
amount' )
import Data.Bool ( bool )
import Data.List ( sortOn )
import Data.Ratio ( Ratio )
withMinimumDate ::
(Date -> [a])
-> [Transaction]
-> [a]
withMinimumDate _ [] =
[]
withMinimumDate f ts@(_:_) =
f (minimum (fmap date' ts))
sortedByDateTransactions ::
([(Integer, Transaction)] -> [(Integer, x)])
-> [Transaction]
-> [x]
sortedByDateTransactions f ts =
let ts' =
sortOn (date' . view _2) (zip [0..] ts)
r =
sortOn (view _1) (f ts')
in fmap (view _2) r
cumulativeSumTransactions ::
[Transaction]
-> [Amount]
cumulativeSumTransactions =
sortedByDateTransactions
(\case
[] ->
[]
(n, h):t ->
scanl (\(_, a) -> over _2 (\t' -> amount' t' <> a)) (n, amount' h) t
)
cumulativeDays ::
[Transaction]
-> [Integer]
cumulativeDays ts =
withMinimumDate (`cumulativeDays'` ts) ts
cumulativeDays' ::
Date
-> [Transaction]
-> [Integer]
cumulativeDays' d =
sortedByDateTransactions (fmap (fmap (\t -> date' t `diffDates` d + 1)))
cumulativePerDay ::
[Transaction]
-> [Ratio Integer]
cumulativePerDay ts =
withMinimumDate (`cumulativePerDay'` ts) ts
cumulativePerDay' ::
Date
-> [Transaction]
-> [Ratio Integer]
cumulativePerDay' dt txs =
zipWith (\a i -> bool (realAmount a / fromInteger i) 0 (i == 0)) (cumulativeSumTransactions txs) (cumulativeDays' dt txs)