{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
module Hledger.Reports.PostingsReport (
PostingsReport,
PostingsReportItem,
postingsReport,
mkpostingsReportItem,
tests_PostingsReport
)
where
import Data.List (nub, sortOn)
import Data.List.Extra (nubSort)
import Data.Maybe (isJust, isNothing)
import Data.Text (Text)
import Data.Time.Calendar (Day)
import Safe (headMay)
import Hledger.Data
import Hledger.Query
import Hledger.Utils
import Hledger.Reports.ReportOptions
type PostingsReport = [PostingsReportItem]
type PostingsReportItem = (Maybe Day
,Maybe Period
,Maybe Text
,Posting
,MixedAmount
)
instance HasAmounts PostingsReportItem where
styleAmounts :: Map CommoditySymbol AmountStyle
-> PostingsReportItem -> PostingsReportItem
styleAmounts Map CommoditySymbol AmountStyle
styles (Maybe Day
a,Maybe Period
b,Maybe CommoditySymbol
c,Posting
d,MixedAmount
e) = (Maybe Day
a,Maybe Period
b,Maybe CommoditySymbol
c,forall a. HasAmounts a => Map CommoditySymbol AmountStyle -> a -> a
styleAmounts Map CommoditySymbol AmountStyle
styles Posting
d,forall a. HasAmounts a => Map CommoditySymbol AmountStyle -> a -> a
styleAmounts Map CommoditySymbol AmountStyle
styles MixedAmount
e)
type SummaryPosting = (Posting, Period)
postingsReport :: ReportSpec -> Journal -> PostingsReport
postingsReport :: ReportSpec -> Journal -> PostingsReport
postingsReport rspec :: ReportSpec
rspec@ReportSpec{_rsReportOpts :: ReportSpec -> ReportOpts
_rsReportOpts=ropts :: ReportOpts
ropts@ReportOpts{Bool
Int
[CommoditySymbol]
[Status]
Maybe Int
Maybe CommoditySymbol
Maybe NormalSign
Maybe ValuationType
Maybe ConversionOp
Interval
Period
StringFormat
Layout
AccountListMode
BalanceAccumulation
BalanceCalculation
layout_ :: ReportOpts -> Layout
transpose_ :: ReportOpts -> Bool
color_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
invert_ :: ReportOpts -> Bool
percent_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
summary_only_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
declared_ :: ReportOpts -> Bool
drop_ :: ReportOpts -> Int
accountlistmode_ :: ReportOpts -> AccountListMode
budgetpat_ :: ReportOpts -> Maybe CommoditySymbol
balanceaccum_ :: ReportOpts -> BalanceAccumulation
balancecalc_ :: ReportOpts -> BalanceCalculation
txn_dates_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
average_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [CommoditySymbol]
pretty_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
real_ :: ReportOpts -> Bool
no_elide_ :: ReportOpts -> Bool
empty_ :: ReportOpts -> Bool
date2_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
infer_prices_ :: ReportOpts -> Bool
value_ :: ReportOpts -> Maybe ValuationType
conversionop_ :: ReportOpts -> Maybe ConversionOp
statuses_ :: ReportOpts -> [Status]
interval_ :: ReportOpts -> Interval
period_ :: ReportOpts -> Period
layout_ :: Layout
transpose_ :: Bool
color_ :: Bool
normalbalance_ :: Maybe NormalSign
invert_ :: Bool
percent_ :: Bool
sort_amount_ :: Bool
show_costs_ :: Bool
summary_only_ :: Bool
no_total_ :: Bool
row_total_ :: Bool
declared_ :: Bool
drop_ :: Int
accountlistmode_ :: AccountListMode
budgetpat_ :: Maybe CommoditySymbol
balanceaccum_ :: BalanceAccumulation
balancecalc_ :: BalanceCalculation
txn_dates_ :: Bool
related_ :: Bool
average_ :: Bool
querystring_ :: [CommoditySymbol]
pretty_ :: Bool
format_ :: StringFormat
real_ :: Bool
no_elide_ :: Bool
empty_ :: Bool
date2_ :: Bool
depth_ :: Maybe Int
infer_prices_ :: Bool
value_ :: Maybe ValuationType
conversionop_ :: Maybe ConversionOp
statuses_ :: [Status]
interval_ :: Interval
period_ :: Period
..}} Journal
j = PostingsReport
items
where
(DateSpan
reportspan, [DateSpan]
colspans) = Journal -> ReportSpec -> (DateSpan, [DateSpan])
reportSpanBothDates Journal
j ReportSpec
rspec
whichdate :: WhichDate
whichdate = ReportOpts -> WhichDate
whichDate ReportOpts
ropts
mdepth :: Maybe Int
mdepth = Query -> Maybe Int
queryDepth forall a b. (a -> b) -> a -> b
$ ReportSpec -> Query
_rsQuery ReportSpec
rspec
multiperiod :: Bool
multiperiod = Interval
interval_ forall a. Eq a => a -> a -> Bool
/= Interval
NoInterval
([Posting]
precedingps, [Posting]
reportps) = ReportSpec -> Journal -> DateSpan -> ([Posting], [Posting])
matchedPostingsBeforeAndDuring ReportSpec
rspec Journal
j DateSpan
reportspan
[(Posting, Maybe Period)]
displayps :: [(Posting, Maybe Period)]
| Bool
multiperiod = [(Posting
p', forall a. a -> Maybe a
Just Period
period') | (Posting
p', Period
period') <- [Posting] -> [(Posting, Period)]
summariseps [Posting]
reportps]
| Bool
otherwise = [(Posting
p', forall a. Maybe a
Nothing) | Posting
p' <- [Posting]
reportps]
where
summariseps :: [Posting] -> [(Posting, Period)]
summariseps = WhichDate
-> Maybe Int
-> Bool
-> [DateSpan]
-> [Posting]
-> [(Posting, Period)]
summarisePostingsByInterval WhichDate
whichdate Maybe Int
mdepth Bool
showempty [DateSpan]
colspans
showempty :: Bool
showempty = Bool
empty_ Bool -> Bool -> Bool
|| Bool
average_
items :: PostingsReport
items =
forall a. Show a => String -> a -> a
dbg4 String
"postingsReport items" forall a b. (a -> b) -> a -> b
$
[(Posting, Maybe Period)]
-> (Posting, Maybe Period)
-> WhichDate
-> Maybe Int
-> MixedAmount
-> (Int -> MixedAmount -> MixedAmount -> MixedAmount)
-> Int
-> PostingsReport
postingsReportItems [(Posting, Maybe Period)]
displayps (Posting
nullposting,forall a. Maybe a
Nothing) WhichDate
whichdate Maybe Int
mdepth MixedAmount
startbal Int -> MixedAmount -> MixedAmount -> MixedAmount
runningcalc Int
startnum
where
historical :: Bool
historical = BalanceAccumulation
balanceaccum_ forall a. Eq a => a -> a -> Bool
== BalanceAccumulation
Historical
startbal :: MixedAmount
startbal | Bool
average_ = if Bool
historical then MixedAmount
precedingavg else MixedAmount
nullmixedamt
| Bool
otherwise = if Bool
historical then MixedAmount
precedingsum else MixedAmount
nullmixedamt
where
precedingsum :: MixedAmount
precedingsum = [Posting] -> MixedAmount
sumPostings [Posting]
precedingps
precedingavg :: MixedAmount
precedingavg = Quantity -> MixedAmount -> MixedAmount
divideMixedAmount (forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length [Posting]
precedingps) MixedAmount
precedingsum
runningcalc :: Int -> MixedAmount -> MixedAmount -> MixedAmount
runningcalc = ReportOpts -> Int -> MixedAmount -> MixedAmount -> MixedAmount
registerRunningCalculationFn ReportOpts
ropts
startnum :: Int
startnum = if Bool
historical then forall (t :: * -> *) a. Foldable t => t a -> Int
length [Posting]
precedingps forall a. Num a => a -> a -> a
+ Int
1 else Int
1
registerRunningCalculationFn :: ReportOpts -> (Int -> MixedAmount -> MixedAmount -> MixedAmount)
registerRunningCalculationFn :: ReportOpts -> Int -> MixedAmount -> MixedAmount -> MixedAmount
registerRunningCalculationFn ReportOpts
ropts
| ReportOpts -> Bool
average_ ReportOpts
ropts = \Int
i MixedAmount
avg MixedAmount
amt -> MixedAmount
avg MixedAmount -> MixedAmount -> MixedAmount
`maPlus` Quantity -> MixedAmount -> MixedAmount
divideMixedAmount (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i) (MixedAmount
amt MixedAmount -> MixedAmount -> MixedAmount
`maMinus` MixedAmount
avg)
| Bool
otherwise = \Int
_ MixedAmount
bal MixedAmount
amt -> MixedAmount
bal MixedAmount -> MixedAmount -> MixedAmount
`maPlus` MixedAmount
amt
matchedPostingsBeforeAndDuring :: ReportSpec -> Journal -> DateSpan -> ([Posting],[Posting])
matchedPostingsBeforeAndDuring :: ReportSpec -> Journal -> DateSpan -> ([Posting], [Posting])
matchedPostingsBeforeAndDuring rspec :: ReportSpec
rspec@ReportSpec{_rsReportOpts :: ReportSpec -> ReportOpts
_rsReportOpts=ReportOpts
ropts,_rsQuery :: ReportSpec -> Query
_rsQuery=Query
q} Journal
j DateSpan
reportspan =
forall a. Show a => String -> a -> a
dbg5 String
"beforeps, duringps" forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> ([a], [a])
span (Query
beforestartq Query -> Posting -> Bool
`matchesPosting`) [Posting]
beforeandduringps
where
beforestartq :: Query
beforestartq = forall a. Show a => String -> a -> a
dbg3 String
"beforestartq" forall a b. (a -> b) -> a -> b
$ DateSpan -> Query
dateqtype forall a b. (a -> b) -> a -> b
$ Maybe EFDay -> Maybe EFDay -> DateSpan
DateSpan forall a. Maybe a
Nothing (Day -> EFDay
Exact forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DateSpan -> Maybe Day
spanStart DateSpan
reportspan)
beforeandduringps :: [Posting]
beforeandduringps =
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn (WhichDate -> Posting -> Day
postingDateOrDate2 (ReportOpts -> WhichDate
whichDate ReportOpts
ropts))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (if ReportOpts -> Bool
invert_ ReportOpts
ropts then forall a b. (a -> b) -> [a] -> [b]
map Posting -> Posting
negatePostingAmount else forall a. a -> a
id)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Journal -> [Posting]
journalPostings
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (if ReportOpts -> Bool
show_costs_ ReportOpts
ropts then forall a. a -> a
id else (MixedAmount -> MixedAmount) -> Journal -> Journal
journalMapPostingAmounts MixedAmount -> MixedAmount
mixedAmountStripPrices)
forall a b. (a -> b) -> a -> b
$ ReportSpec -> Journal -> Journal
journalValueAndFilterPostings ReportSpec
rspec{_rsQuery :: Query
_rsQuery=Query
beforeandduringq} Journal
j
beforeandduringq :: Query
beforeandduringq = forall a. Show a => String -> a -> a
dbg4 String
"beforeandduringq" forall a b. (a -> b) -> a -> b
$ [Query] -> Query
And [Query -> Query
depthless forall a b. (a -> b) -> a -> b
$ Query -> Query
dateless Query
q, Query
beforeendq]
where
depthless :: Query -> Query
depthless = (Query -> Bool) -> Query -> Query
filterQuery (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Query -> Bool
queryIsDepth)
dateless :: Query -> Query
dateless = (Query -> Bool) -> Query -> Query
filterQuery (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Query -> Bool
queryIsDateOrDate2)
beforeendq :: Query
beforeendq = DateSpan -> Query
dateqtype forall a b. (a -> b) -> a -> b
$ Maybe EFDay -> Maybe EFDay -> DateSpan
DateSpan forall a. Maybe a
Nothing (Day -> EFDay
Exact forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DateSpan -> Maybe Day
spanEnd DateSpan
reportspan)
dateqtype :: DateSpan -> Query
dateqtype = if Query -> Bool
queryIsDate2 Query
dateq Bool -> Bool -> Bool
|| (Query -> Bool
queryIsDate Query
dateq Bool -> Bool -> Bool
&& ReportOpts -> Bool
date2_ ReportOpts
ropts) then DateSpan -> Query
Date2 else DateSpan -> Query
Date
where
dateq :: Query
dateq = forall a. Show a => String -> a -> a
dbg4 String
"dateq" forall a b. (a -> b) -> a -> b
$ (Query -> Bool) -> Query -> Query
filterQuery Query -> Bool
queryIsDateOrDate2 forall a b. (a -> b) -> a -> b
$ forall a. Show a => String -> a -> a
dbg4 String
"q" Query
q
postingsReportItems :: [(Posting,Maybe Period)] -> (Posting,Maybe Period) -> WhichDate -> Maybe Int -> MixedAmount -> (Int -> MixedAmount -> MixedAmount -> MixedAmount) -> Int -> [PostingsReportItem]
postingsReportItems :: [(Posting, Maybe Period)]
-> (Posting, Maybe Period)
-> WhichDate
-> Maybe Int
-> MixedAmount
-> (Int -> MixedAmount -> MixedAmount -> MixedAmount)
-> Int
-> PostingsReport
postingsReportItems [] (Posting, Maybe Period)
_ WhichDate
_ Maybe Int
_ MixedAmount
_ Int -> MixedAmount -> MixedAmount -> MixedAmount
_ Int
_ = []
postingsReportItems ((Posting
p,Maybe Period
mperiod):[(Posting, Maybe Period)]
ps) (Posting
pprev,Maybe Period
mperiodprev) WhichDate
wd Maybe Int
d MixedAmount
b Int -> MixedAmount -> MixedAmount -> MixedAmount
runningcalcfn Int
itemnum =
PostingsReportItem
iforall a. a -> [a] -> [a]
:([(Posting, Maybe Period)]
-> (Posting, Maybe Period)
-> WhichDate
-> Maybe Int
-> MixedAmount
-> (Int -> MixedAmount -> MixedAmount -> MixedAmount)
-> Int
-> PostingsReport
postingsReportItems [(Posting, Maybe Period)]
ps (Posting
p,Maybe Period
mperiod) WhichDate
wd Maybe Int
d MixedAmount
b' Int -> MixedAmount -> MixedAmount -> MixedAmount
runningcalcfn (Int
itemnumforall a. Num a => a -> a -> a
+Int
1))
where
i :: PostingsReportItem
i = Bool
-> Bool
-> WhichDate
-> Maybe Period
-> Posting
-> MixedAmount
-> PostingsReportItem
mkpostingsReportItem Bool
showdate Bool
showdesc WhichDate
wd Maybe Period
mperiod Posting
p' MixedAmount
b'
(Bool
showdate, Bool
showdesc) | forall a. Maybe a -> Bool
isJust Maybe Period
mperiod = (Maybe Period
mperiod forall a. Eq a => a -> a -> Bool
/= Maybe Period
mperiodprev, Bool
False)
| Bool
otherwise = (Bool
isfirstintxn Bool -> Bool -> Bool
|| Bool
isdifferentdate, Bool
isfirstintxn)
isfirstintxn :: Bool
isfirstintxn = Posting -> Maybe Transaction
ptransaction Posting
p forall a. Eq a => a -> a -> Bool
/= Posting -> Maybe Transaction
ptransaction Posting
pprev
isdifferentdate :: Bool
isdifferentdate = case WhichDate
wd of WhichDate
PrimaryDate -> Posting -> Day
postingDate Posting
p forall a. Eq a => a -> a -> Bool
/= Posting -> Day
postingDate Posting
pprev
WhichDate
SecondaryDate -> Posting -> Day
postingDate2 Posting
p forall a. Eq a => a -> a -> Bool
/= Posting -> Day
postingDate2 Posting
pprev
p' :: Posting
p' = Posting
p{paccount :: CommoditySymbol
paccount= Maybe Int -> CommoditySymbol -> CommoditySymbol
clipOrEllipsifyAccountName Maybe Int
d forall a b. (a -> b) -> a -> b
$ Posting -> CommoditySymbol
paccount Posting
p}
b' :: MixedAmount
b' = Int -> MixedAmount -> MixedAmount -> MixedAmount
runningcalcfn Int
itemnum MixedAmount
b forall a b. (a -> b) -> a -> b
$ Posting -> MixedAmount
pamount Posting
p
mkpostingsReportItem :: Bool -> Bool -> WhichDate -> Maybe Period -> Posting -> MixedAmount -> PostingsReportItem
mkpostingsReportItem :: Bool
-> Bool
-> WhichDate
-> Maybe Period
-> Posting
-> MixedAmount
-> PostingsReportItem
mkpostingsReportItem Bool
showdate Bool
showdesc WhichDate
wd Maybe Period
mperiod Posting
p MixedAmount
b =
(if Bool
showdate then forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ WhichDate -> Posting -> Day
postingDateOrDate2 WhichDate
wd Posting
p else forall a. Maybe a
Nothing
,Maybe Period
mperiod
,if Bool
showdesc then Transaction -> CommoditySymbol
tdescription forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Posting -> Maybe Transaction
ptransaction Posting
p else forall a. Maybe a
Nothing
,Posting
p
,MixedAmount
b
)
summarisePostingsByInterval :: WhichDate -> Maybe Int -> Bool -> [DateSpan] -> [Posting] -> [SummaryPosting]
summarisePostingsByInterval :: WhichDate
-> Maybe Int
-> Bool
-> [DateSpan]
-> [Posting]
-> [(Posting, Period)]
summarisePostingsByInterval WhichDate
wd Maybe Int
mdepth Bool
showempty [DateSpan]
colspans =
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(DateSpan
s,[Posting]
ps) -> DateSpan
-> WhichDate
-> Maybe Int
-> Bool
-> [Posting]
-> [(Posting, Period)]
summarisePostingsInDateSpan DateSpan
s WhichDate
wd Maybe Int
mdepth Bool
showempty [Posting]
ps)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a.
Bool -> (a -> Day) -> [DateSpan] -> [a] -> [(DateSpan, [a])]
groupByDateSpan Bool
showempty (WhichDate -> Posting -> Day
postingDateOrDate2 WhichDate
wd) [DateSpan]
colspans
summarisePostingsInDateSpan :: DateSpan -> WhichDate -> Maybe Int -> Bool -> [Posting] -> [SummaryPosting]
summarisePostingsInDateSpan :: DateSpan
-> WhichDate
-> Maybe Int
-> Bool
-> [Posting]
-> [(Posting, Period)]
summarisePostingsInDateSpan spn :: DateSpan
spn@(DateSpan Maybe EFDay
b Maybe EFDay
e) WhichDate
wd Maybe Int
mdepth Bool
showempty [Posting]
ps
| forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Posting]
ps Bool -> Bool -> Bool
&& (forall a. Maybe a -> Bool
isNothing Maybe EFDay
b Bool -> Bool -> Bool
|| forall a. Maybe a -> Bool
isNothing Maybe EFDay
e) = []
| forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Posting]
ps Bool -> Bool -> Bool
&& Bool
showempty = [(Posting
summaryp, DateSpan -> Period
dateSpanAsPeriod DateSpan
spn)]
| Bool
otherwise = [(Posting, Period)]
summarypes
where
postingdate :: Posting -> Day
postingdate = if WhichDate
wd forall a. Eq a => a -> a -> Bool
== WhichDate
PrimaryDate then Posting -> Day
postingDate else Posting -> Day
postingDate2
b' :: Day
b' = forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall b a. b -> (a -> b) -> Maybe a -> b
maybe Day
nulldate Posting -> Day
postingdate forall a b. (a -> b) -> a -> b
$ forall a. [a] -> Maybe a
headMay [Posting]
ps) EFDay -> Day
fromEFDay Maybe EFDay
b
summaryp :: Posting
summaryp = Posting
nullposting{pdate :: Maybe Day
pdate=forall a. a -> Maybe a
Just Day
b'}
clippedanames :: [CommoditySymbol]
clippedanames = forall a. Eq a => [a] -> [a]
nub forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (Maybe Int -> CommoditySymbol -> CommoditySymbol
clipAccountName Maybe Int
mdepth) [CommoditySymbol]
anames
summaryps :: [Posting]
summaryps | Maybe Int
mdepth forall a. Eq a => a -> a -> Bool
== forall a. a -> Maybe a
Just Int
0 = [Posting
summaryp{paccount :: CommoditySymbol
paccount=CommoditySymbol
"...",pamount :: MixedAmount
pamount=[Posting] -> MixedAmount
sumPostings [Posting]
ps}]
| Bool
otherwise = [Posting
summaryp{paccount :: CommoditySymbol
paccount=CommoditySymbol
a,pamount :: MixedAmount
pamount=CommoditySymbol -> MixedAmount
balance CommoditySymbol
a} | CommoditySymbol
a <- [CommoditySymbol]
clippedanames]
summarypes :: [(Posting, Period)]
summarypes = forall a b. (a -> b) -> [a] -> [b]
map (, DateSpan -> Period
dateSpanAsPeriod DateSpan
spn) forall a b. (a -> b) -> a -> b
$ (if Bool
showempty then forall a. a -> a
id else forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. MixedAmount -> Bool
mixedAmountLooksZero forall b c a. (b -> c) -> (a -> b) -> a -> c
. Posting -> MixedAmount
pamount)) [Posting]
summaryps
anames :: [CommoditySymbol]
anames = forall a. Ord a => [a] -> [a]
nubSort forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map Posting -> CommoditySymbol
paccount [Posting]
ps
accts :: [Account]
accts = [Posting] -> [Account]
accountsFromPostings [Posting]
ps
balance :: CommoditySymbol -> MixedAmount
balance CommoditySymbol
a = forall b a. b -> (a -> b) -> Maybe a -> b
maybe MixedAmount
nullmixedamt Account -> MixedAmount
bal forall a b. (a -> b) -> a -> b
$ CommoditySymbol -> [Account] -> Maybe Account
lookupAccount CommoditySymbol
a [Account]
accts
where
bal :: Account -> MixedAmount
bal = if CommoditySymbol -> Bool
isclipped CommoditySymbol
a then Account -> MixedAmount
aibalance else Account -> MixedAmount
aebalance
isclipped :: CommoditySymbol -> Bool
isclipped CommoditySymbol
a' = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (CommoditySymbol -> Int
accountNameLevel CommoditySymbol
a' forall a. Ord a => a -> a -> Bool
>=) Maybe Int
mdepth
negatePostingAmount :: Posting -> Posting
negatePostingAmount :: Posting -> Posting
negatePostingAmount = (MixedAmount -> MixedAmount) -> Posting -> Posting
postingTransformAmount forall a. Num a => a -> a
negate
tests_PostingsReport :: TestTree
tests_PostingsReport = String -> [TestTree] -> TestTree
testGroup String
"PostingsReport" [
String -> Assertion -> TestTree
testCase String
"postingsReport" forall a b. (a -> b) -> a -> b
$ do
let (Query
query, Journal
journal) gives :: (Query, Journal) -> Int -> Assertion
`gives` Int
n = (forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ ReportSpec -> Journal -> PostingsReport
postingsReport ReportSpec
defreportspec{_rsQuery :: Query
_rsQuery=Query
query} Journal
journal) forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= Int
n
(Query
Any, Journal
nulljournal) (Query, Journal) -> Int -> Assertion
`gives` Int
0
(Query
Any, Journal
samplejournal) (Query, Journal) -> Int -> Assertion
`gives` Int
13
(Int -> Query
Depth Int
2, Journal
samplejournal) (Query, Journal) -> Int -> Assertion
`gives` Int
13
([Query] -> Query
And [Int -> Query
Depth Int
1, Status -> Query
StatusQ Status
Cleared, Regexp -> Query
Acct (CommoditySymbol -> Regexp
toRegex' CommoditySymbol
"expenses")], Journal
samplejournal) (Query, Journal) -> Int -> Assertion
`gives` Int
2
([Query] -> Query
And [[Query] -> Query
And [Int -> Query
Depth Int
1, Status -> Query
StatusQ Status
Cleared], Regexp -> Query
Acct (CommoditySymbol -> Regexp
toRegex' CommoditySymbol
"expenses")], Journal
samplejournal) (Query, Journal) -> Int -> Assertion
`gives` Int
2
(forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ ReportSpec -> Journal -> PostingsReport
postingsReport ReportSpec
defreportspec Journal
samplejournal) forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= Int
13
(forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ ReportSpec -> Journal -> PostingsReport
postingsReport ReportSpec
defreportspec{_rsReportOpts :: ReportOpts
_rsReportOpts=ReportOpts
defreportopts{interval_ :: Interval
interval_=Int -> Interval
Months Int
1}} Journal
samplejournal) forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= Int
11
(forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ ReportSpec -> Journal -> PostingsReport
postingsReport ReportSpec
defreportspec{_rsReportOpts :: ReportOpts
_rsReportOpts=ReportOpts
defreportopts{interval_ :: Interval
interval_=Int -> Interval
Months Int
1, empty_ :: Bool
empty_=Bool
True}} Journal
samplejournal) forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= Int
20
(forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ ReportSpec -> Journal -> PostingsReport
postingsReport ReportSpec
defreportspec{_rsQuery :: Query
_rsQuery=Regexp -> Query
Acct forall a b. (a -> b) -> a -> b
$ CommoditySymbol -> Regexp
toRegex' CommoditySymbol
"assets:bank:checking"} Journal
samplejournal) forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= Int
5
,String -> Assertion -> TestTree
testCase String
"summarisePostingsByInterval" forall a b. (a -> b) -> a -> b
$
WhichDate
-> Maybe Int
-> Bool
-> [DateSpan]
-> [Posting]
-> [(Posting, Period)]
summarisePostingsByInterval WhichDate
PrimaryDate forall a. Maybe a
Nothing Bool
False [Maybe EFDay -> Maybe EFDay -> DateSpan
DateSpan forall a. Maybe a
Nothing forall a. Maybe a
Nothing] [] forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= []
]