{-# LANGUAGE CPP #-}
{-# LANGUAGE ExtendedDefaultRules #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
module Hledger.Cli.Commands.Balance (
balancemode
,balance
,balanceReportAsText
,balanceReportItemAsText
,multiBalanceReportAsText
,multiBalanceReportAsCsv
,multiBalanceReportAsHtml
,multiBalanceReportHtmlRows
,balanceReportAsTable
,balanceReportTableAsText
,tests_Balance
) where
import Data.Default (def)
import Data.List (intercalate, transpose)
import Data.Maybe (fromMaybe, maybeToList)
#if !(MIN_VERSION_base(4,11,0))
import Data.Semigroup ((<>))
#endif
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Data.Time (fromGregorian)
import System.Console.CmdArgs.Explicit as C
import Lucid as L
import Text.Tabular as T
import Text.Tabular.AsciiWide as T
import Hledger
import Hledger.Cli.CliOptions
import Hledger.Cli.Utils
import Hledger.Read.CsvReader (CSV, printCSV)
balancemode :: Mode RawOpts
balancemode = CommandDoc
-> [Flag RawOpts]
-> [(CommandDoc, [Flag RawOpts])]
-> [Flag RawOpts]
-> ([Arg RawOpts], Maybe (Arg RawOpts))
-> Mode RawOpts
hledgerCommandMode
$(embedFileRelative "Hledger/Cli/Commands/Balance.txt")
([[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"change"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"change")
CommandDoc
"show balance change in each period (default)"
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"cumulative"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"cumulative")
CommandDoc
"show balance change accumulated across periods (in multicolumn reports)"
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"historical",CommandDoc
"H"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"historical")
CommandDoc
"show historical ending balance in each period (includes postings before report start date)\n "
]
[Flag RawOpts] -> [Flag RawOpts] -> [Flag RawOpts]
forall a. [a] -> [a] -> [a]
++ Bool -> [Flag RawOpts]
flattreeflags Bool
True [Flag RawOpts] -> [Flag RawOpts] -> [Flag RawOpts]
forall a. [a] -> [a] -> [a]
++
[[CommandDoc]
-> Update RawOpts -> CommandDoc -> CommandDoc -> Flag RawOpts
forall a.
[CommandDoc] -> Update a -> CommandDoc -> CommandDoc -> Flag a
flagReq [CommandDoc
"drop"] (\CommandDoc
s RawOpts
opts -> RawOpts -> Either CommandDoc RawOpts
forall a b. b -> Either a b
Right (RawOpts -> Either CommandDoc RawOpts)
-> RawOpts -> Either CommandDoc RawOpts
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc -> RawOpts -> RawOpts
setopt CommandDoc
"drop" CommandDoc
s RawOpts
opts) CommandDoc
"N" CommandDoc
"omit N leading account name parts (in flat mode)"
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"average",CommandDoc
"A"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"average") CommandDoc
"show a row average column (in multicolumn reports)"
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"row-total",CommandDoc
"T"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"row-total") CommandDoc
"show a row total column (in multicolumn reports)"
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"no-total",CommandDoc
"N"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"no-total") CommandDoc
"omit the final total row"
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"no-elide"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"no-elide") CommandDoc
"don't squash boring parent accounts (in tree mode); don't show only 2 commodities per amount"
,[CommandDoc]
-> Update RawOpts -> CommandDoc -> CommandDoc -> Flag RawOpts
forall a.
[CommandDoc] -> Update a -> CommandDoc -> CommandDoc -> Flag a
flagReq [CommandDoc
"format"] (\CommandDoc
s RawOpts
opts -> RawOpts -> Either CommandDoc RawOpts
forall a b. b -> Either a b
Right (RawOpts -> Either CommandDoc RawOpts)
-> RawOpts -> Either CommandDoc RawOpts
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc -> RawOpts -> RawOpts
setopt CommandDoc
"format" CommandDoc
s RawOpts
opts) CommandDoc
"FORMATSTR" CommandDoc
"use this custom line format (in simple reports)"
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"pretty-tables"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"pretty-tables") CommandDoc
"use unicode to display prettier tables"
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"sort-amount",CommandDoc
"S"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"sort-amount") CommandDoc
"sort by amount instead of account code/name (in flat mode). With multiple columns, sorts by the row total, or by row average if that is displayed."
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"percent", CommandDoc
"%"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"percent") CommandDoc
"express values in percentage of each column's total"
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"invert"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"invert") CommandDoc
"display all amounts with reversed sign"
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"transpose"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"transpose") CommandDoc
"transpose rows and columns"
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"budget"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"budget") CommandDoc
"show performance compared to budget goals defined by periodic transactions"
,[CommandDoc] -> Flag RawOpts
outputFormatFlag [CommandDoc
"txt",CommandDoc
"html",CommandDoc
"csv",CommandDoc
"json"]
,Flag RawOpts
outputFileFlag
]
)
[(CommandDoc, [Flag RawOpts])
generalflagsgroup1]
[Flag RawOpts]
hiddenflags
([], Arg RawOpts -> Maybe (Arg RawOpts)
forall a. a -> Maybe a
Just (Arg RawOpts -> Maybe (Arg RawOpts))
-> Arg RawOpts -> Maybe (Arg RawOpts)
forall a b. (a -> b) -> a -> b
$ CommandDoc -> Arg RawOpts
argsFlag CommandDoc
"[QUERY]")
balance :: CliOpts -> Journal -> IO ()
balance :: CliOpts -> Journal -> IO ()
balance opts :: CliOpts
opts@CliOpts{rawopts_ :: CliOpts -> RawOpts
rawopts_=RawOpts
rawopts,reportspec_ :: CliOpts -> ReportSpec
reportspec_=ReportSpec
rspec} Journal
j = do
let ropts :: ReportOpts
ropts@ReportOpts{Bool
Int
[Text]
[Status]
Maybe Int
Maybe ValuationType
Maybe DateSpan
Maybe NormalSign
BalanceType
AccountListMode
StringFormat
Period
Interval
period_ :: ReportOpts -> Period
interval_ :: ReportOpts -> Interval
statuses_ :: ReportOpts -> [Status]
value_ :: ReportOpts -> Maybe ValuationType
infer_value_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
date2_ :: ReportOpts -> Bool
empty_ :: ReportOpts -> Bool
no_elide_ :: ReportOpts -> Bool
real_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
querystring_ :: ReportOpts -> [Text]
average_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
balancetype_ :: ReportOpts -> BalanceType
accountlistmode_ :: ReportOpts -> AccountListMode
drop_ :: ReportOpts -> Int
row_total_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
pretty_tables_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
percent_ :: ReportOpts -> Bool
invert_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
color_ :: ReportOpts -> Bool
forecast_ :: ReportOpts -> Maybe DateSpan
transpose_ :: ReportOpts -> Bool
transpose_ :: Bool
forecast_ :: Maybe DateSpan
color_ :: Bool
normalbalance_ :: Maybe NormalSign
invert_ :: Bool
percent_ :: Bool
sort_amount_ :: Bool
pretty_tables_ :: Bool
no_total_ :: Bool
row_total_ :: Bool
drop_ :: Int
accountlistmode_ :: AccountListMode
balancetype_ :: BalanceType
txn_dates_ :: Bool
related_ :: Bool
average_ :: Bool
querystring_ :: [Text]
format_ :: StringFormat
real_ :: Bool
no_elide_ :: Bool
empty_ :: Bool
date2_ :: Bool
depth_ :: Maybe Int
infer_value_ :: Bool
value_ :: Maybe ValuationType
statuses_ :: [Status]
interval_ :: Interval
period_ :: Period
..} = ReportSpec -> ReportOpts
rsOpts ReportSpec
rspec
budget :: Bool
budget = CommandDoc -> RawOpts -> Bool
boolopt CommandDoc
"budget" RawOpts
rawopts
multiperiod :: Bool
multiperiod = Interval
interval_ Interval -> Interval -> Bool
forall a. Eq a => a -> a -> Bool
/= Interval
NoInterval
fmt :: CommandDoc
fmt = CliOpts -> CommandDoc
outputFormatFromOpts CliOpts
opts
if Bool
budget then do
let reportspan :: DateSpan
reportspan = Journal -> ReportSpec -> DateSpan
reportSpan Journal
j ReportSpec
rspec
budgetreport :: BudgetReport
budgetreport = ReportSpec -> Bool -> DateSpan -> Journal -> BudgetReport
budgetReport ReportSpec
rspec Bool
assrt DateSpan
reportspan Journal
j
where
assrt :: Bool
assrt = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ InputOpts -> Bool
ignore_assertions_ (InputOpts -> Bool) -> InputOpts -> Bool
forall a b. (a -> b) -> a -> b
$ CliOpts -> InputOpts
inputopts_ CliOpts
opts
render :: BudgetReport -> CommandDoc
render = case CommandDoc
fmt of
CommandDoc
"txt" -> ReportOpts -> BudgetReport -> CommandDoc
budgetReportAsText ReportOpts
ropts
CommandDoc
"json" -> (CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++CommandDoc
"\n") (CommandDoc -> CommandDoc)
-> (BudgetReport -> CommandDoc) -> BudgetReport -> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> CommandDoc
TL.unpack (Text -> CommandDoc)
-> (BudgetReport -> Text) -> BudgetReport -> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BudgetReport -> Text
forall a. ToJSON a => a -> Text
toJsonText
CommandDoc
"csv" -> (CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++CommandDoc
"\n") (CommandDoc -> CommandDoc)
-> (BudgetReport -> CommandDoc) -> BudgetReport -> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CSV -> CommandDoc
printCSV (CSV -> CommandDoc)
-> (BudgetReport -> CSV) -> BudgetReport -> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> BudgetReport -> CSV
budgetReportAsCsv ReportOpts
ropts
CommandDoc
_ -> CommandDoc -> BudgetReport -> CommandDoc
forall a b. a -> b -> a
const (CommandDoc -> BudgetReport -> CommandDoc)
-> CommandDoc -> BudgetReport -> CommandDoc
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc
forall a. CommandDoc -> a
error' (CommandDoc -> CommandDoc) -> CommandDoc -> CommandDoc
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc
unsupportedOutputFormatError CommandDoc
fmt
CliOpts -> CommandDoc -> IO ()
writeOutput CliOpts
opts (CommandDoc -> IO ()) -> CommandDoc -> IO ()
forall a b. (a -> b) -> a -> b
$ BudgetReport -> CommandDoc
render BudgetReport
budgetreport
else
if Bool
multiperiod then do
let report :: MultiBalanceReport
report = ReportSpec -> Journal -> MultiBalanceReport
multiBalanceReport ReportSpec
rspec Journal
j
render :: MultiBalanceReport -> CommandDoc
render = case CommandDoc
fmt of
CommandDoc
"txt" -> ReportOpts -> MultiBalanceReport -> CommandDoc
multiBalanceReportAsText ReportOpts
ropts
CommandDoc
"csv" -> (CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++CommandDoc
"\n") (CommandDoc -> CommandDoc)
-> (MultiBalanceReport -> CommandDoc)
-> MultiBalanceReport
-> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CSV -> CommandDoc
printCSV (CSV -> CommandDoc)
-> (MultiBalanceReport -> CSV) -> MultiBalanceReport -> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> MultiBalanceReport -> CSV
multiBalanceReportAsCsv ReportOpts
ropts
CommandDoc
"html" -> (CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++CommandDoc
"\n") (CommandDoc -> CommandDoc)
-> (MultiBalanceReport -> CommandDoc)
-> MultiBalanceReport
-> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> CommandDoc
TL.unpack (Text -> CommandDoc)
-> (MultiBalanceReport -> Text) -> MultiBalanceReport -> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Html () -> Text
forall a. Html a -> Text
L.renderText (Html () -> Text)
-> (MultiBalanceReport -> Html ()) -> MultiBalanceReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> MultiBalanceReport -> Html ()
multiBalanceReportAsHtml ReportOpts
ropts
CommandDoc
"json" -> (CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++CommandDoc
"\n") (CommandDoc -> CommandDoc)
-> (MultiBalanceReport -> CommandDoc)
-> MultiBalanceReport
-> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> CommandDoc
TL.unpack (Text -> CommandDoc)
-> (MultiBalanceReport -> Text) -> MultiBalanceReport -> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MultiBalanceReport -> Text
forall a. ToJSON a => a -> Text
toJsonText
CommandDoc
_ -> CommandDoc -> MultiBalanceReport -> CommandDoc
forall a b. a -> b -> a
const (CommandDoc -> MultiBalanceReport -> CommandDoc)
-> CommandDoc -> MultiBalanceReport -> CommandDoc
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc
forall a. CommandDoc -> a
error' (CommandDoc -> CommandDoc) -> CommandDoc -> CommandDoc
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc
unsupportedOutputFormatError CommandDoc
fmt
CliOpts -> CommandDoc -> IO ()
writeOutput CliOpts
opts (CommandDoc -> IO ()) -> CommandDoc -> IO ()
forall a b. (a -> b) -> a -> b
$ MultiBalanceReport -> CommandDoc
render MultiBalanceReport
report
else do
let report :: BalanceReport
report = ReportSpec -> Journal -> BalanceReport
balanceReport ReportSpec
rspec Journal
j
render :: ReportOpts -> BalanceReport -> CommandDoc
render = case CommandDoc
fmt of
CommandDoc
"txt" -> ReportOpts -> BalanceReport -> CommandDoc
balanceReportAsText
CommandDoc
"csv" -> \ReportOpts
ropts BalanceReport
r -> (CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++ CommandDoc
"\n") (CommandDoc -> CommandDoc) -> CommandDoc -> CommandDoc
forall a b. (a -> b) -> a -> b
$ CSV -> CommandDoc
printCSV (CSV -> CommandDoc) -> CSV -> CommandDoc
forall a b. (a -> b) -> a -> b
$ ReportOpts -> BalanceReport -> CSV
balanceReportAsCsv ReportOpts
ropts BalanceReport
r
CommandDoc
"json" -> (BalanceReport -> CommandDoc)
-> ReportOpts -> BalanceReport -> CommandDoc
forall a b. a -> b -> a
const ((BalanceReport -> CommandDoc)
-> ReportOpts -> BalanceReport -> CommandDoc)
-> (BalanceReport -> CommandDoc)
-> ReportOpts
-> BalanceReport
-> CommandDoc
forall a b. (a -> b) -> a -> b
$ (CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++CommandDoc
"\n") (CommandDoc -> CommandDoc)
-> (BalanceReport -> CommandDoc) -> BalanceReport -> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> CommandDoc
TL.unpack (Text -> CommandDoc)
-> (BalanceReport -> Text) -> BalanceReport -> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BalanceReport -> Text
forall a. ToJSON a => a -> Text
toJsonText
CommandDoc
_ -> (BalanceReport -> CommandDoc)
-> ReportOpts -> BalanceReport -> CommandDoc
forall a b. a -> b -> a
const ((BalanceReport -> CommandDoc)
-> ReportOpts -> BalanceReport -> CommandDoc)
-> (BalanceReport -> CommandDoc)
-> ReportOpts
-> BalanceReport
-> CommandDoc
forall a b. (a -> b) -> a -> b
$ CommandDoc -> BalanceReport -> CommandDoc
forall a. CommandDoc -> a
error' (CommandDoc -> BalanceReport -> CommandDoc)
-> CommandDoc -> BalanceReport -> CommandDoc
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc
unsupportedOutputFormatError CommandDoc
fmt
CliOpts -> CommandDoc -> IO ()
writeOutput CliOpts
opts (CommandDoc -> IO ()) -> CommandDoc -> IO ()
forall a b. (a -> b) -> a -> b
$ ReportOpts -> BalanceReport -> CommandDoc
render ReportOpts
ropts BalanceReport
report
balanceReportAsCsv :: ReportOpts -> BalanceReport -> CSV
balanceReportAsCsv :: ReportOpts -> BalanceReport -> CSV
balanceReportAsCsv ReportOpts
opts ([BalanceReportItem]
items, MixedAmount
total) =
[CommandDoc
"account",CommandDoc
"balance"] [CommandDoc] -> CSV -> CSV
forall a. a -> [a] -> [a]
:
[[Text -> CommandDoc
T.unpack (Text -> CommandDoc) -> Text -> CommandDoc
forall a b. (a -> b) -> a -> b
$ Int -> Text -> Text
accountNameDrop (ReportOpts -> Int
drop_ ReportOpts
opts) Text
a, Bool -> MixedAmount -> CommandDoc
showMixedAmountOneLineWithoutPrice Bool
False MixedAmount
b] | (Text
a, Text
_, Int
_, MixedAmount
b) <- [BalanceReportItem]
items]
CSV -> CSV -> CSV
forall a. [a] -> [a] -> [a]
++
if ReportOpts -> Bool
no_total_ ReportOpts
opts
then []
else [[CommandDoc
"total", Bool -> MixedAmount -> CommandDoc
showMixedAmountOneLineWithoutPrice Bool
False MixedAmount
total]]
balanceReportAsText :: ReportOpts -> BalanceReport -> String
balanceReportAsText :: ReportOpts -> BalanceReport -> CommandDoc
balanceReportAsText ReportOpts
opts (([BalanceReportItem]
items, MixedAmount
total)) = [CommandDoc] -> CommandDoc
unlines ([CommandDoc] -> CommandDoc) -> [CommandDoc] -> CommandDoc
forall a b. (a -> b) -> a -> b
$
CSV -> [CommandDoc]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat CSV
lines [CommandDoc] -> [CommandDoc] -> [CommandDoc]
forall a. [a] -> [a] -> [a]
++ if ReportOpts -> Bool
no_total_ ReportOpts
opts then [] else CommandDoc
overline CommandDoc -> [CommandDoc] -> [CommandDoc]
forall a. a -> [a] -> [a]
: [CommandDoc]
totallines
where
lines :: CSV
lines = (BalanceReportItem -> [CommandDoc]) -> [BalanceReportItem] -> CSV
forall a b. (a -> b) -> [a] -> [b]
map (ReportOpts -> BalanceReportItem -> [CommandDoc]
balanceReportItemAsText ReportOpts
opts) [BalanceReportItem]
items
acctcolwidth :: Int
acctcolwidth = [Int] -> Int
forall a. Integral a => [a] -> a
maximum' [Text -> Int
T.length Text
fullname | (Text
fullname, Text
_, Int
_, MixedAmount
_) <- [BalanceReportItem]
items]
totallines :: [CommandDoc]
totallines = (CommandDoc -> CommandDoc) -> [CommandDoc] -> [CommandDoc]
forall a b. (a -> b) -> [a] -> [b]
map CommandDoc -> CommandDoc
rstrip ([CommandDoc] -> [CommandDoc]) -> [CommandDoc] -> [CommandDoc]
forall a b. (a -> b) -> a -> b
$ ReportOpts -> (Text, Int, MixedAmount) -> [CommandDoc]
renderBalanceReportItem ReportOpts
opts (Int -> Text -> Text
T.replicate (Int
acctcolwidthInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Text
" ", Int
0, MixedAmount
total)
overlinewidth :: Int
overlinewidth = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe ([Int] -> Int
forall a. Integral a => [a] -> a
maximum' ([Int] -> Int) -> ([CommandDoc] -> [Int]) -> [CommandDoc] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CommandDoc -> Int) -> [CommandDoc] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map CommandDoc -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([CommandDoc] -> Int) -> [CommandDoc] -> Int
forall a b. (a -> b) -> a -> b
$ CSV -> [CommandDoc]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat CSV
lines) (Maybe Int -> Int)
-> (StringFormat -> Maybe Int) -> StringFormat -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StringFormat -> Maybe Int
overlineWidth (StringFormat -> Int) -> StringFormat -> Int
forall a b. (a -> b) -> a -> b
$ ReportOpts -> StringFormat
format_ ReportOpts
opts
overline :: CommandDoc
overline = Int -> Char -> CommandDoc
forall a. Int -> a -> [a]
replicate Int
overlinewidth Char
'-'
balanceReportItemAsText :: ReportOpts -> BalanceReportItem -> [String]
balanceReportItemAsText :: ReportOpts -> BalanceReportItem -> [CommandDoc]
balanceReportItemAsText ReportOpts
opts (Text
_, Text
accountName, Int
depth, MixedAmount
amt) =
ReportOpts -> (Text, Int, MixedAmount) -> [CommandDoc]
renderBalanceReportItem ReportOpts
opts (
Text
accountName,
Int
depth,
MixedAmount -> MixedAmount
normaliseMixedAmountSquashPricesForDisplay MixedAmount
amt
)
renderBalanceReportItem :: ReportOpts -> (AccountName, Int, MixedAmount) -> [String]
renderBalanceReportItem :: ReportOpts -> (Text, Int, MixedAmount) -> [CommandDoc]
renderBalanceReportItem ReportOpts
opts (Text
acctname, Int
depth, MixedAmount
total) =
CommandDoc -> [CommandDoc]
lines (CommandDoc -> [CommandDoc]) -> CommandDoc -> [CommandDoc]
forall a b. (a -> b) -> a -> b
$ case ReportOpts -> StringFormat
format_ ReportOpts
opts of
OneLine Maybe Int
_ [StringFormatComponent]
comps -> [CommandDoc] -> CommandDoc
concatOneLine ([CommandDoc] -> CommandDoc) -> [CommandDoc] -> CommandDoc
forall a b. (a -> b) -> a -> b
$ [StringFormatComponent] -> [CommandDoc]
render1 [StringFormatComponent]
comps
TopAligned Maybe Int
_ [StringFormatComponent]
comps -> [CommandDoc] -> CommandDoc
concatBottomPadded ([CommandDoc] -> CommandDoc) -> [CommandDoc] -> CommandDoc
forall a b. (a -> b) -> a -> b
$ [StringFormatComponent] -> [CommandDoc]
render [StringFormatComponent]
comps
BottomAligned Maybe Int
_ [StringFormatComponent]
comps -> [CommandDoc] -> CommandDoc
concatTopPadded ([CommandDoc] -> CommandDoc) -> [CommandDoc] -> CommandDoc
forall a b. (a -> b) -> a -> b
$ [StringFormatComponent] -> [CommandDoc]
render [StringFormatComponent]
comps
where
render1 :: [StringFormatComponent] -> [CommandDoc]
render1 = (StringFormatComponent -> CommandDoc)
-> [StringFormatComponent] -> [CommandDoc]
forall a b. (a -> b) -> [a] -> [b]
map (ReportOpts
-> (Text, Int, MixedAmount) -> StringFormatComponent -> CommandDoc
renderComponent1 ReportOpts
opts (Text
acctname, Int
depth, MixedAmount
total))
render :: [StringFormatComponent] -> [CommandDoc]
render = (StringFormatComponent -> CommandDoc)
-> [StringFormatComponent] -> [CommandDoc]
forall a b. (a -> b) -> [a] -> [b]
map (ReportOpts
-> (Text, Int, MixedAmount) -> StringFormatComponent -> CommandDoc
renderComponent ReportOpts
opts (Text
acctname, Int
depth, MixedAmount
total))
renderComponent :: ReportOpts -> (AccountName, Int, MixedAmount) -> StringFormatComponent -> String
renderComponent :: ReportOpts
-> (Text, Int, MixedAmount) -> StringFormatComponent -> CommandDoc
renderComponent ReportOpts
_ (Text, Int, MixedAmount)
_ (FormatLiteral CommandDoc
s) = CommandDoc
s
renderComponent ReportOpts
opts (Text
acctname, Int
depth, MixedAmount
total) (FormatField Bool
ljust Maybe Int
min Maybe Int
max ReportItemField
field) = case ReportItemField
field of
ReportItemField
DepthSpacerField -> Bool -> Maybe Int -> Maybe Int -> CommandDoc -> CommandDoc
formatString Bool
ljust Maybe Int
forall a. Maybe a
Nothing Maybe Int
max (CommandDoc -> CommandDoc) -> CommandDoc -> CommandDoc
forall a b. (a -> b) -> a -> b
$ Int -> Char -> CommandDoc
forall a. Int -> a -> [a]
replicate Int
d Char
' '
where d :: Int
d = case Maybe Int
min of
Just Int
m -> Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
m
Maybe Int
Nothing -> Int
depth
ReportItemField
AccountField -> Bool -> Maybe Int -> Maybe Int -> CommandDoc -> CommandDoc
formatString Bool
ljust Maybe Int
min Maybe Int
max (Text -> CommandDoc
T.unpack Text
acctname)
ReportItemField
TotalField -> (CommandDoc, Int) -> CommandDoc
forall a b. (a, b) -> a
fst ((CommandDoc, Int) -> CommandDoc)
-> (CommandDoc, Int) -> CommandDoc
forall a b. (a -> b) -> a -> b
$ (Amount -> CommandDoc)
-> Maybe Int
-> Maybe Int
-> Bool
-> MixedAmount
-> (CommandDoc, Int)
showMixed Amount -> CommandDoc
showAmountWithoutPrice Maybe Int
min Maybe Int
max (ReportOpts -> Bool
color_ ReportOpts
opts) MixedAmount
total
ReportItemField
_ -> CommandDoc
""
renderComponent1 :: ReportOpts -> (AccountName, Int, MixedAmount) -> StringFormatComponent -> String
renderComponent1 :: ReportOpts
-> (Text, Int, MixedAmount) -> StringFormatComponent -> CommandDoc
renderComponent1 ReportOpts
_ (Text, Int, MixedAmount)
_ (FormatLiteral CommandDoc
s) = CommandDoc
s
renderComponent1 ReportOpts
opts (Text
acctname, Int
depth, MixedAmount
total) (FormatField Bool
ljust Maybe Int
min Maybe Int
max ReportItemField
field) = case ReportItemField
field of
ReportItemField
AccountField -> Bool -> Maybe Int -> Maybe Int -> CommandDoc -> CommandDoc
formatString Bool
ljust Maybe Int
min Maybe Int
max ((CommandDoc -> [CommandDoc] -> CommandDoc
forall a. [a] -> [[a]] -> [a]
intercalate CommandDoc
", " ([CommandDoc] -> CommandDoc)
-> (CommandDoc -> [CommandDoc]) -> CommandDoc -> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CommandDoc -> [CommandDoc]
lines) (CommandDoc -> CommandDoc
indented (Text -> CommandDoc
T.unpack Text
acctname)))
where
indented :: CommandDoc -> CommandDoc
indented = ((Int -> Char -> CommandDoc
forall a. Int -> a -> [a]
replicate (Int
depthInt -> Int -> Int
forall a. Num a => a -> a -> a
*Int
2) Char
' ')CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++)
ReportItemField
TotalField -> (CommandDoc, Int) -> CommandDoc
forall a b. (a, b) -> a
fst ((CommandDoc, Int) -> CommandDoc)
-> (CommandDoc, Int) -> CommandDoc
forall a b. (a -> b) -> a -> b
$ (Amount -> CommandDoc)
-> Maybe Int
-> Maybe Int
-> Bool
-> MixedAmount
-> (CommandDoc, Int)
showMixedOneLine Amount -> CommandDoc
showAmountWithoutPrice Maybe Int
min Maybe Int
max (ReportOpts -> Bool
color_ ReportOpts
opts) MixedAmount
total
ReportItemField
_ -> CommandDoc
""
multiBalanceReportAsCsv :: ReportOpts -> MultiBalanceReport -> CSV
multiBalanceReportAsCsv :: ReportOpts -> MultiBalanceReport -> CSV
multiBalanceReportAsCsv opts :: ReportOpts
opts@ReportOpts{Bool
average_ :: Bool
average_ :: ReportOpts -> Bool
average_, Bool
row_total_ :: Bool
row_total_ :: ReportOpts -> Bool
row_total_}
(PeriodicReport [DateSpan]
colspans [PeriodicReportRow DisplayName MixedAmount]
items (PeriodicReportRow ()
_ [MixedAmount]
coltotals MixedAmount
tot MixedAmount
avg)) =
CSV -> CSV
forall a. [[a]] -> [[a]]
maybetranspose (CSV -> CSV) -> CSV -> CSV
forall a b. (a -> b) -> a -> b
$
(CommandDoc
"Account" CommandDoc -> [CommandDoc] -> [CommandDoc]
forall a. a -> [a] -> [a]
: (DateSpan -> CommandDoc) -> [DateSpan] -> [CommandDoc]
forall a b. (a -> b) -> [a] -> [b]
map DateSpan -> CommandDoc
showDateSpan [DateSpan]
colspans
[CommandDoc] -> [CommandDoc] -> [CommandDoc]
forall a. [a] -> [a] -> [a]
++ [CommandDoc
"Total" | Bool
row_total_]
[CommandDoc] -> [CommandDoc] -> [CommandDoc]
forall a. [a] -> [a] -> [a]
++ [CommandDoc
"Average" | Bool
average_]
) [CommandDoc] -> CSV -> CSV
forall a. a -> [a] -> [a]
:
[Text -> CommandDoc
T.unpack (DisplayName -> Text
displayName DisplayName
a) CommandDoc -> [CommandDoc] -> [CommandDoc]
forall a. a -> [a] -> [a]
:
(MixedAmount -> CommandDoc) -> [MixedAmount] -> [CommandDoc]
forall a b. (a -> b) -> [a] -> [b]
map (Bool -> MixedAmount -> CommandDoc
showMixedAmountOneLineWithoutPrice Bool
False)
([MixedAmount]
amts
[MixedAmount] -> [MixedAmount] -> [MixedAmount]
forall a. [a] -> [a] -> [a]
++ [MixedAmount
rowtot | Bool
row_total_]
[MixedAmount] -> [MixedAmount] -> [MixedAmount]
forall a. [a] -> [a] -> [a]
++ [MixedAmount
rowavg | Bool
average_])
| PeriodicReportRow DisplayName
a [MixedAmount]
amts MixedAmount
rowtot MixedAmount
rowavg <- [PeriodicReportRow DisplayName MixedAmount]
items]
CSV -> CSV -> CSV
forall a. [a] -> [a] -> [a]
++
if ReportOpts -> Bool
no_total_ ReportOpts
opts
then []
else [CommandDoc
"Total:" CommandDoc -> [CommandDoc] -> [CommandDoc]
forall a. a -> [a] -> [a]
:
(MixedAmount -> CommandDoc) -> [MixedAmount] -> [CommandDoc]
forall a b. (a -> b) -> [a] -> [b]
map (Bool -> MixedAmount -> CommandDoc
showMixedAmountOneLineWithoutPrice Bool
False) (
[MixedAmount]
coltotals
[MixedAmount] -> [MixedAmount] -> [MixedAmount]
forall a. [a] -> [a] -> [a]
++ [MixedAmount
tot | Bool
row_total_]
[MixedAmount] -> [MixedAmount] -> [MixedAmount]
forall a. [a] -> [a] -> [a]
++ [MixedAmount
avg | Bool
average_]
)]
where
maybetranspose :: [[a]] -> [[a]]
maybetranspose | ReportOpts -> Bool
transpose_ ReportOpts
opts = [[a]] -> [[a]]
forall a. [[a]] -> [[a]]
transpose
| Bool
otherwise = [[a]] -> [[a]]
forall a. a -> a
id
multiBalanceReportAsHtml :: ReportOpts -> MultiBalanceReport -> Html ()
multiBalanceReportAsHtml :: ReportOpts -> MultiBalanceReport -> Html ()
multiBalanceReportAsHtml ReportOpts
ropts MultiBalanceReport
mbr =
let
(Html ()
headingsrow,[Html ()]
bodyrows,Maybe (Html ())
mtotalsrow) = ReportOpts
-> MultiBalanceReport -> (Html (), [Html ()], Maybe (Html ()))
multiBalanceReportHtmlRows ReportOpts
ropts MultiBalanceReport
mbr
in
Html () -> Html ()
forall arg result. Term arg result => arg -> result
table_ (Html () -> Html ()) -> Html () -> Html ()
forall a b. (a -> b) -> a -> b
$ [Html ()] -> Html ()
forall a. Monoid a => [a] -> a
mconcat ([Html ()] -> Html ()) -> [Html ()] -> Html ()
forall a b. (a -> b) -> a -> b
$
[Html ()
headingsrow]
[Html ()] -> [Html ()] -> [Html ()]
forall a. [a] -> [a] -> [a]
++ [Html ()]
bodyrows
[Html ()] -> [Html ()] -> [Html ()]
forall a. [a] -> [a] -> [a]
++ Maybe (Html ()) -> [Html ()]
forall a. Maybe a -> [a]
maybeToList Maybe (Html ())
mtotalsrow
multiBalanceReportHtmlRows :: ReportOpts -> MultiBalanceReport -> (Html (), [Html ()], Maybe (Html ()))
multiBalanceReportHtmlRows :: ReportOpts
-> MultiBalanceReport -> (Html (), [Html ()], Maybe (Html ()))
multiBalanceReportHtmlRows ReportOpts
ropts MultiBalanceReport
mbr =
let
[CommandDoc]
headingsrow:CSV
rest | ReportOpts -> Bool
transpose_ ReportOpts
ropts = CommandDoc -> CSV
forall a. CommandDoc -> a
error' CommandDoc
"Sorry, --transpose with HTML output is not yet supported"
| Bool
otherwise = ReportOpts -> MultiBalanceReport -> CSV
multiBalanceReportAsCsv ReportOpts
ropts MultiBalanceReport
mbr
(CSV
bodyrows, Maybe [CommandDoc]
mtotalsrow) | ReportOpts -> Bool
no_total_ ReportOpts
ropts = (CSV
rest, Maybe [CommandDoc]
forall a. Maybe a
Nothing)
| Bool
otherwise = (CSV -> CSV
forall a. [a] -> [a]
init CSV
rest, [CommandDoc] -> Maybe [CommandDoc]
forall a. a -> Maybe a
Just ([CommandDoc] -> Maybe [CommandDoc])
-> [CommandDoc] -> Maybe [CommandDoc]
forall a b. (a -> b) -> a -> b
$ CSV -> [CommandDoc]
forall a. [a] -> a
last CSV
rest)
in
(ReportOpts -> [CommandDoc] -> Html ()
multiBalanceReportHtmlHeadRow ReportOpts
ropts [CommandDoc]
headingsrow
,([CommandDoc] -> Html ()) -> CSV -> [Html ()]
forall a b. (a -> b) -> [a] -> [b]
map (ReportOpts -> [CommandDoc] -> Html ()
multiBalanceReportHtmlBodyRow ReportOpts
ropts) CSV
bodyrows
,ReportOpts -> [CommandDoc] -> Html ()
multiBalanceReportHtmlFootRow ReportOpts
ropts ([CommandDoc] -> Html ()) -> Maybe [CommandDoc] -> Maybe (Html ())
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe [CommandDoc]
mtotalsrow
)
multiBalanceReportHtmlHeadRow :: ReportOpts -> [String] -> Html ()
multiBalanceReportHtmlHeadRow :: ReportOpts -> [CommandDoc] -> Html ()
multiBalanceReportHtmlHeadRow ReportOpts
_ [] = Html ()
forall a. Monoid a => a
mempty
multiBalanceReportHtmlHeadRow ReportOpts
ropts (CommandDoc
acct:[CommandDoc]
rest) =
let
defstyle :: Attribute
defstyle = Text -> Attribute
forall arg result. TermRaw arg result => arg -> result
style_ Text
""
([CommandDoc]
amts,[CommandDoc]
tot,[CommandDoc]
avg)
| ReportOpts -> Bool
row_total_ ReportOpts
ropts Bool -> Bool -> Bool
&& ReportOpts -> Bool
average_ ReportOpts
ropts = ([CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init ([CommandDoc] -> [CommandDoc]) -> [CommandDoc] -> [CommandDoc]
forall a b. (a -> b) -> a -> b
$ [CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init [CommandDoc]
rest, [[CommandDoc] -> CommandDoc
forall a. [a] -> a
last ([CommandDoc] -> CommandDoc) -> [CommandDoc] -> CommandDoc
forall a b. (a -> b) -> a -> b
$ [CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init [CommandDoc]
rest], [[CommandDoc] -> CommandDoc
forall a. [a] -> a
last [CommandDoc]
rest])
| ReportOpts -> Bool
row_total_ ReportOpts
ropts = ([CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init [CommandDoc]
rest, [[CommandDoc] -> CommandDoc
forall a. [a] -> a
last [CommandDoc]
rest], [])
| ReportOpts -> Bool
average_ ReportOpts
ropts = ([CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init [CommandDoc]
rest, [], [[CommandDoc] -> CommandDoc
forall a. [a] -> a
last [CommandDoc]
rest])
| Bool
otherwise = ([CommandDoc]
rest, [], [])
in
Html () -> Html ()
forall arg result. Term arg result => arg -> result
tr_ (Html () -> Html ()) -> Html () -> Html ()
forall a b. (a -> b) -> a -> b
$ [Html ()] -> Html ()
forall a. Monoid a => [a] -> a
mconcat ([Html ()] -> Html ()) -> [Html ()] -> Html ()
forall a b. (a -> b) -> a -> b
$
[Attribute] -> Html () -> Html ()
forall arg result. Term arg result => arg -> result
td_ [Text -> Attribute
class_ Text
"account"] (CommandDoc -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml CommandDoc
acct)
Html () -> [Html ()] -> [Html ()]
forall a. a -> [a] -> [a]
: [[Attribute] -> Html () -> Html ()
forall arg result. Term arg result => arg -> result
td_ [Text -> Attribute
class_ Text
"", Attribute
defstyle] (CommandDoc -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml CommandDoc
a) | CommandDoc
a <- [CommandDoc]
amts]
[Html ()] -> [Html ()] -> [Html ()]
forall a. [a] -> [a] -> [a]
++ [[Attribute] -> Html () -> Html ()
forall arg result. Term arg result => arg -> result
td_ [Text -> Attribute
class_ Text
"rowtotal", Attribute
defstyle] (CommandDoc -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml CommandDoc
a) | CommandDoc
a <- [CommandDoc]
tot]
[Html ()] -> [Html ()] -> [Html ()]
forall a. [a] -> [a] -> [a]
++ [[Attribute] -> Html () -> Html ()
forall arg result. Term arg result => arg -> result
td_ [Text -> Attribute
class_ Text
"rowaverage", Attribute
defstyle] (CommandDoc -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml CommandDoc
a) | CommandDoc
a <- [CommandDoc]
avg]
multiBalanceReportHtmlBodyRow :: ReportOpts -> [String] -> Html ()
multiBalanceReportHtmlBodyRow :: ReportOpts -> [CommandDoc] -> Html ()
multiBalanceReportHtmlBodyRow ReportOpts
_ [] = Html ()
forall a. Monoid a => a
mempty
multiBalanceReportHtmlBodyRow ReportOpts
ropts (CommandDoc
label:[CommandDoc]
rest) =
let
defstyle :: Attribute
defstyle = Text -> Attribute
forall arg result. TermRaw arg result => arg -> result
style_ Text
"text-align:right"
([CommandDoc]
amts,[CommandDoc]
tot,[CommandDoc]
avg)
| ReportOpts -> Bool
row_total_ ReportOpts
ropts Bool -> Bool -> Bool
&& ReportOpts -> Bool
average_ ReportOpts
ropts = ([CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init ([CommandDoc] -> [CommandDoc]) -> [CommandDoc] -> [CommandDoc]
forall a b. (a -> b) -> a -> b
$ [CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init [CommandDoc]
rest, [[CommandDoc] -> CommandDoc
forall a. [a] -> a
last ([CommandDoc] -> CommandDoc) -> [CommandDoc] -> CommandDoc
forall a b. (a -> b) -> a -> b
$ [CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init [CommandDoc]
rest], [[CommandDoc] -> CommandDoc
forall a. [a] -> a
last [CommandDoc]
rest])
| ReportOpts -> Bool
row_total_ ReportOpts
ropts = ([CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init [CommandDoc]
rest, [[CommandDoc] -> CommandDoc
forall a. [a] -> a
last [CommandDoc]
rest], [])
| ReportOpts -> Bool
average_ ReportOpts
ropts = ([CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init [CommandDoc]
rest, [], [[CommandDoc] -> CommandDoc
forall a. [a] -> a
last [CommandDoc]
rest])
| Bool
otherwise = ([CommandDoc]
rest, [], [])
in
Html () -> Html ()
forall arg result. Term arg result => arg -> result
tr_ (Html () -> Html ()) -> Html () -> Html ()
forall a b. (a -> b) -> a -> b
$ [Html ()] -> Html ()
forall a. Monoid a => [a] -> a
mconcat ([Html ()] -> Html ()) -> [Html ()] -> Html ()
forall a b. (a -> b) -> a -> b
$
[Attribute] -> Html () -> Html ()
forall arg result. Term arg result => arg -> result
td_ [Text -> Attribute
class_ Text
"account", Text -> Attribute
forall arg result. TermRaw arg result => arg -> result
style_ Text
"text-align:left"] (CommandDoc -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml CommandDoc
label)
Html () -> [Html ()] -> [Html ()]
forall a. a -> [a] -> [a]
: [[Attribute] -> Html () -> Html ()
forall arg result. Term arg result => arg -> result
td_ [Text -> Attribute
class_ Text
"amount", Attribute
defstyle] (CommandDoc -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml CommandDoc
a) | CommandDoc
a <- [CommandDoc]
amts]
[Html ()] -> [Html ()] -> [Html ()]
forall a. [a] -> [a] -> [a]
++ [[Attribute] -> Html () -> Html ()
forall arg result. Term arg result => arg -> result
td_ [Text -> Attribute
class_ Text
"amount rowtotal", Attribute
defstyle] (CommandDoc -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml CommandDoc
a) | CommandDoc
a <- [CommandDoc]
tot]
[Html ()] -> [Html ()] -> [Html ()]
forall a. [a] -> [a] -> [a]
++ [[Attribute] -> Html () -> Html ()
forall arg result. Term arg result => arg -> result
td_ [Text -> Attribute
class_ Text
"amount rowaverage", Attribute
defstyle] (CommandDoc -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml CommandDoc
a) | CommandDoc
a <- [CommandDoc]
avg]
multiBalanceReportHtmlFootRow :: ReportOpts -> [String] -> Html ()
ReportOpts
_ropts [] = Html ()
forall a. Monoid a => a
mempty
multiBalanceReportHtmlFootRow ReportOpts
ropts (CommandDoc
acct:[CommandDoc]
rest) =
let
defstyle :: Attribute
defstyle = Text -> Attribute
forall arg result. TermRaw arg result => arg -> result
style_ Text
"text-align:right"
([CommandDoc]
amts,[CommandDoc]
tot,[CommandDoc]
avg)
| ReportOpts -> Bool
row_total_ ReportOpts
ropts Bool -> Bool -> Bool
&& ReportOpts -> Bool
average_ ReportOpts
ropts = ([CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init ([CommandDoc] -> [CommandDoc]) -> [CommandDoc] -> [CommandDoc]
forall a b. (a -> b) -> a -> b
$ [CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init [CommandDoc]
rest, [[CommandDoc] -> CommandDoc
forall a. [a] -> a
last ([CommandDoc] -> CommandDoc) -> [CommandDoc] -> CommandDoc
forall a b. (a -> b) -> a -> b
$ [CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init [CommandDoc]
rest], [[CommandDoc] -> CommandDoc
forall a. [a] -> a
last [CommandDoc]
rest])
| ReportOpts -> Bool
row_total_ ReportOpts
ropts = ([CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init [CommandDoc]
rest, [[CommandDoc] -> CommandDoc
forall a. [a] -> a
last [CommandDoc]
rest], [])
| ReportOpts -> Bool
average_ ReportOpts
ropts = ([CommandDoc] -> [CommandDoc]
forall a. [a] -> [a]
init [CommandDoc]
rest, [], [[CommandDoc] -> CommandDoc
forall a. [a] -> a
last [CommandDoc]
rest])
| Bool
otherwise = ([CommandDoc]
rest, [], [])
in
Html () -> Html ()
forall arg result. Term arg result => arg -> result
tr_ (Html () -> Html ()) -> Html () -> Html ()
forall a b. (a -> b) -> a -> b
$ [Html ()] -> Html ()
forall a. Monoid a => [a] -> a
mconcat ([Html ()] -> Html ()) -> [Html ()] -> Html ()
forall a b. (a -> b) -> a -> b
$
[Attribute] -> Html () -> Html ()
forall arg result. Term arg result => arg -> result
th_ [Text -> Attribute
forall arg result. TermRaw arg result => arg -> result
style_ Text
"text-align:left"] (CommandDoc -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml CommandDoc
acct)
Html () -> [Html ()] -> [Html ()]
forall a. a -> [a] -> [a]
: [[Attribute] -> Html () -> Html ()
forall arg result. Term arg result => arg -> result
th_ [Text -> Attribute
class_ Text
"amount coltotal", Attribute
defstyle] (CommandDoc -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml CommandDoc
a) | CommandDoc
a <- [CommandDoc]
amts]
[Html ()] -> [Html ()] -> [Html ()]
forall a. [a] -> [a] -> [a]
++ [[Attribute] -> Html () -> Html ()
forall arg result. Term arg result => arg -> result
th_ [Text -> Attribute
class_ Text
"amount coltotal", Attribute
defstyle] (CommandDoc -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml CommandDoc
a) | CommandDoc
a <- [CommandDoc]
tot]
[Html ()] -> [Html ()] -> [Html ()]
forall a. [a] -> [a] -> [a]
++ [[Attribute] -> Html () -> Html ()
forall arg result. Term arg result => arg -> result
th_ [Text -> Attribute
class_ Text
"amount colaverage", Attribute
defstyle] (CommandDoc -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml CommandDoc
a) | CommandDoc
a <- [CommandDoc]
avg]
multiBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> String
multiBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> CommandDoc
multiBalanceReportAsText ropts :: ReportOpts
ropts@ReportOpts{Bool
Int
[Text]
[Status]
Maybe Int
Maybe ValuationType
Maybe DateSpan
Maybe NormalSign
BalanceType
AccountListMode
StringFormat
Period
Interval
transpose_ :: Bool
forecast_ :: Maybe DateSpan
color_ :: Bool
normalbalance_ :: Maybe NormalSign
invert_ :: Bool
percent_ :: Bool
sort_amount_ :: Bool
pretty_tables_ :: Bool
no_total_ :: Bool
row_total_ :: Bool
drop_ :: Int
accountlistmode_ :: AccountListMode
balancetype_ :: BalanceType
txn_dates_ :: Bool
related_ :: Bool
average_ :: Bool
querystring_ :: [Text]
format_ :: StringFormat
real_ :: Bool
no_elide_ :: Bool
empty_ :: Bool
date2_ :: Bool
depth_ :: Maybe Int
infer_value_ :: Bool
value_ :: Maybe ValuationType
statuses_ :: [Status]
interval_ :: Interval
period_ :: Period
period_ :: ReportOpts -> Period
interval_ :: ReportOpts -> Interval
statuses_ :: ReportOpts -> [Status]
value_ :: ReportOpts -> Maybe ValuationType
infer_value_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
date2_ :: ReportOpts -> Bool
empty_ :: ReportOpts -> Bool
no_elide_ :: ReportOpts -> Bool
real_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
querystring_ :: ReportOpts -> [Text]
average_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
balancetype_ :: ReportOpts -> BalanceType
accountlistmode_ :: ReportOpts -> AccountListMode
drop_ :: ReportOpts -> Int
row_total_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
pretty_tables_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
percent_ :: ReportOpts -> Bool
invert_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
color_ :: ReportOpts -> Bool
forecast_ :: ReportOpts -> Maybe DateSpan
transpose_ :: ReportOpts -> Bool
..} MultiBalanceReport
r =
CommandDoc
title CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++ CommandDoc
"\n\n" CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++ (ReportOpts -> Table CommandDoc CommandDoc MixedAmount -> CommandDoc
balanceReportTableAsText ReportOpts
ropts (Table CommandDoc CommandDoc MixedAmount -> CommandDoc)
-> Table CommandDoc CommandDoc MixedAmount -> CommandDoc
forall a b. (a -> b) -> a -> b
$ ReportOpts
-> MultiBalanceReport -> Table CommandDoc CommandDoc MixedAmount
balanceReportAsTable ReportOpts
ropts MultiBalanceReport
r)
where
title :: CommandDoc
title = CommandDoc
mtitle CommandDoc -> CommandDoc -> CommandDoc
forall a. Semigroup a => a -> a -> a
<> CommandDoc
" in " CommandDoc -> CommandDoc -> CommandDoc
forall a. Semigroup a => a -> a -> a
<> DateSpan -> CommandDoc
showDateSpan (MultiBalanceReport -> DateSpan
forall a b. PeriodicReport a b -> DateSpan
periodicReportSpan MultiBalanceReport
r) CommandDoc -> CommandDoc -> CommandDoc
forall a. Semigroup a => a -> a -> a
<> CommandDoc
valuationdesc CommandDoc -> CommandDoc -> CommandDoc
forall a. Semigroup a => a -> a -> a
<> CommandDoc
":"
mtitle :: CommandDoc
mtitle = case BalanceType
balancetype_ of
BalanceType
PeriodChange -> CommandDoc
"Balance changes"
BalanceType
CumulativeChange -> CommandDoc
"Ending balances (cumulative)"
BalanceType
HistoricalBalance -> CommandDoc
"Ending balances (historical)"
valuationdesc :: CommandDoc
valuationdesc = case Maybe ValuationType
value_ of
Just (AtCost Maybe Text
_mc) -> CommandDoc
", valued at cost"
Just (AtThen Maybe Text
_mc) -> CommandDoc -> CommandDoc
forall a. CommandDoc -> a
error' CommandDoc
unsupportedValueThenError
Just (AtEnd Maybe Text
_mc) -> CommandDoc
", valued at period ends"
Just (AtNow Maybe Text
_mc) -> CommandDoc
", current value"
Just (AtDefault Maybe Text
_mc) | Bool
multiperiod -> CommandDoc
", valued at period ends"
Just (AtDefault Maybe Text
_mc) -> CommandDoc
", current value"
Just (AtDate Day
d Maybe Text
_mc) -> CommandDoc
", valued at "CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++Day -> CommandDoc
showDate Day
d
Maybe ValuationType
Nothing -> CommandDoc
""
multiperiod :: Bool
multiperiod = Interval
interval_ Interval -> Interval -> Bool
forall a. Eq a => a -> a -> Bool
/= Interval
NoInterval
balanceReportAsTable :: ReportOpts -> MultiBalanceReport -> Table String String MixedAmount
balanceReportAsTable :: ReportOpts
-> MultiBalanceReport -> Table CommandDoc CommandDoc MixedAmount
balanceReportAsTable opts :: ReportOpts
opts@ReportOpts{Bool
average_ :: Bool
average_ :: ReportOpts -> Bool
average_, Bool
row_total_ :: Bool
row_total_ :: ReportOpts -> Bool
row_total_, BalanceType
balancetype_ :: BalanceType
balancetype_ :: ReportOpts -> BalanceType
balancetype_}
(PeriodicReport [DateSpan]
spans [PeriodicReportRow DisplayName MixedAmount]
items (PeriodicReportRow ()
_ [MixedAmount]
coltotals MixedAmount
tot MixedAmount
avg)) =
Table CommandDoc CommandDoc MixedAmount
-> Table CommandDoc CommandDoc MixedAmount
forall rh a. Table rh rh a -> Table rh rh a
maybetranspose (Table CommandDoc CommandDoc MixedAmount
-> Table CommandDoc CommandDoc MixedAmount)
-> Table CommandDoc CommandDoc MixedAmount
-> Table CommandDoc CommandDoc MixedAmount
forall a b. (a -> b) -> a -> b
$
Table CommandDoc CommandDoc MixedAmount
-> Table CommandDoc CommandDoc MixedAmount
forall ch.
Table CommandDoc ch MixedAmount -> Table CommandDoc ch MixedAmount
addtotalrow (Table CommandDoc CommandDoc MixedAmount
-> Table CommandDoc CommandDoc MixedAmount)
-> Table CommandDoc CommandDoc MixedAmount
-> Table CommandDoc CommandDoc MixedAmount
forall a b. (a -> b) -> a -> b
$
Header CommandDoc
-> Header CommandDoc
-> [[MixedAmount]]
-> Table CommandDoc CommandDoc MixedAmount
forall rh ch a. Header rh -> Header ch -> [[a]] -> Table rh ch a
Table
(Properties -> [Header CommandDoc] -> Header CommandDoc
forall h. Properties -> [Header h] -> Header h
T.Group Properties
NoLine ([Header CommandDoc] -> Header CommandDoc)
-> [Header CommandDoc] -> Header CommandDoc
forall a b. (a -> b) -> a -> b
$ (CommandDoc -> Header CommandDoc)
-> [CommandDoc] -> [Header CommandDoc]
forall a b. (a -> b) -> [a] -> [b]
map CommandDoc -> Header CommandDoc
forall h. h -> Header h
Header [CommandDoc]
accts)
(Properties -> [Header CommandDoc] -> Header CommandDoc
forall h. Properties -> [Header h] -> Header h
T.Group Properties
NoLine ([Header CommandDoc] -> Header CommandDoc)
-> [Header CommandDoc] -> Header CommandDoc
forall a b. (a -> b) -> a -> b
$ (CommandDoc -> Header CommandDoc)
-> [CommandDoc] -> [Header CommandDoc]
forall a b. (a -> b) -> [a] -> [b]
map CommandDoc -> Header CommandDoc
forall h. h -> Header h
Header [CommandDoc]
colheadings)
((PeriodicReportRow DisplayName MixedAmount -> [MixedAmount])
-> [PeriodicReportRow DisplayName MixedAmount] -> [[MixedAmount]]
forall a b. (a -> b) -> [a] -> [b]
map PeriodicReportRow DisplayName MixedAmount -> [MixedAmount]
forall a a. PeriodicReportRow a a -> [a]
rowvals [PeriodicReportRow DisplayName MixedAmount]
items)
where
totalscolumn :: Bool
totalscolumn = Bool
row_total_ Bool -> Bool -> Bool
&& BalanceType
balancetype_ BalanceType -> [BalanceType] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [BalanceType
CumulativeChange, BalanceType
HistoricalBalance]
colheadings :: [CommandDoc]
colheadings = (DateSpan -> CommandDoc) -> [DateSpan] -> [CommandDoc]
forall a b. (a -> b) -> [a] -> [b]
map (BalanceType -> [DateSpan] -> DateSpan -> CommandDoc
reportPeriodName BalanceType
balancetype_ [DateSpan]
spans) [DateSpan]
spans
[CommandDoc] -> [CommandDoc] -> [CommandDoc]
forall a. [a] -> [a] -> [a]
++ [CommandDoc
" Total" | Bool
totalscolumn]
[CommandDoc] -> [CommandDoc] -> [CommandDoc]
forall a. [a] -> [a] -> [a]
++ [CommandDoc
"Average" | Bool
average_]
accts :: [CommandDoc]
accts = (PeriodicReportRow DisplayName MixedAmount -> CommandDoc)
-> [PeriodicReportRow DisplayName MixedAmount] -> [CommandDoc]
forall a b. (a -> b) -> [a] -> [b]
map PeriodicReportRow DisplayName MixedAmount -> CommandDoc
forall a. PeriodicReportRow DisplayName a -> CommandDoc
renderacct [PeriodicReportRow DisplayName MixedAmount]
items
renderacct :: PeriodicReportRow DisplayName a -> CommandDoc
renderacct PeriodicReportRow DisplayName a
row =
Int -> Char -> CommandDoc
forall a. Int -> a -> [a]
replicate ((PeriodicReportRow DisplayName a -> Int
forall a. PeriodicReportRow DisplayName a -> Int
prrDepth PeriodicReportRow DisplayName a
row Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
2) Char
' ' CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++ Text -> CommandDoc
T.unpack (PeriodicReportRow DisplayName a -> Text
forall a. PeriodicReportRow DisplayName a -> Text
prrDisplayName PeriodicReportRow DisplayName a
row)
rowvals :: PeriodicReportRow a a -> [a]
rowvals (PeriodicReportRow a
_ [a]
as a
rowtot a
rowavg) = [a]
as
[a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a
rowtot | Bool
totalscolumn]
[a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a
rowavg | Bool
average_]
addtotalrow :: Table CommandDoc ch MixedAmount -> Table CommandDoc ch MixedAmount
addtotalrow | ReportOpts -> Bool
no_total_ ReportOpts
opts = Table CommandDoc ch MixedAmount -> Table CommandDoc ch MixedAmount
forall a. a -> a
id
| Bool
otherwise = (Table CommandDoc ch MixedAmount
-> SemiTable CommandDoc MixedAmount
-> Table CommandDoc ch MixedAmount
forall rh ch a. Table rh ch a -> SemiTable rh a -> Table rh ch a
+----+ (CommandDoc -> [MixedAmount] -> SemiTable CommandDoc MixedAmount
forall rh a. rh -> [a] -> SemiTable rh a
row CommandDoc
"" ([MixedAmount] -> SemiTable CommandDoc MixedAmount)
-> [MixedAmount] -> SemiTable CommandDoc MixedAmount
forall a b. (a -> b) -> a -> b
$
[MixedAmount]
coltotals
[MixedAmount] -> [MixedAmount] -> [MixedAmount]
forall a. [a] -> [a] -> [a]
++ [MixedAmount
tot | Bool
totalscolumn Bool -> Bool -> Bool
&& Bool -> Bool
not ([MixedAmount] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [MixedAmount]
coltotals)]
[MixedAmount] -> [MixedAmount] -> [MixedAmount]
forall a. [a] -> [a] -> [a]
++ [MixedAmount
avg | Bool
average_ Bool -> Bool -> Bool
&& Bool -> Bool
not ([MixedAmount] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [MixedAmount]
coltotals)]
))
maybetranspose :: Table rh rh a -> Table rh rh a
maybetranspose | ReportOpts -> Bool
transpose_ ReportOpts
opts = \(Table Header rh
rh Header rh
ch [[a]]
vals) -> Header rh -> Header rh -> [[a]] -> Table rh rh a
forall rh ch a. Header rh -> Header ch -> [[a]] -> Table rh ch a
Table Header rh
ch Header rh
rh ([[a]] -> [[a]]
forall a. [[a]] -> [[a]]
transpose [[a]]
vals)
| Bool
otherwise = Table rh rh a -> Table rh rh a
forall a. a -> a
id
balanceReportTableAsText :: ReportOpts -> Table String String MixedAmount -> String
balanceReportTableAsText :: ReportOpts -> Table CommandDoc CommandDoc MixedAmount -> CommandDoc
balanceReportTableAsText ReportOpts{Bool
Int
[Text]
[Status]
Maybe Int
Maybe ValuationType
Maybe DateSpan
Maybe NormalSign
BalanceType
AccountListMode
StringFormat
Period
Interval
transpose_ :: Bool
forecast_ :: Maybe DateSpan
color_ :: Bool
normalbalance_ :: Maybe NormalSign
invert_ :: Bool
percent_ :: Bool
sort_amount_ :: Bool
pretty_tables_ :: Bool
no_total_ :: Bool
row_total_ :: Bool
drop_ :: Int
accountlistmode_ :: AccountListMode
balancetype_ :: BalanceType
txn_dates_ :: Bool
related_ :: Bool
average_ :: Bool
querystring_ :: [Text]
format_ :: StringFormat
real_ :: Bool
no_elide_ :: Bool
empty_ :: Bool
date2_ :: Bool
depth_ :: Maybe Int
infer_value_ :: Bool
value_ :: Maybe ValuationType
statuses_ :: [Status]
interval_ :: Interval
period_ :: Period
period_ :: ReportOpts -> Period
interval_ :: ReportOpts -> Interval
statuses_ :: ReportOpts -> [Status]
value_ :: ReportOpts -> Maybe ValuationType
infer_value_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
date2_ :: ReportOpts -> Bool
empty_ :: ReportOpts -> Bool
no_elide_ :: ReportOpts -> Bool
real_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
querystring_ :: ReportOpts -> [Text]
average_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
balancetype_ :: ReportOpts -> BalanceType
accountlistmode_ :: ReportOpts -> AccountListMode
drop_ :: ReportOpts -> Int
row_total_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
pretty_tables_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
percent_ :: ReportOpts -> Bool
invert_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
color_ :: ReportOpts -> Bool
forecast_ :: ReportOpts -> Maybe DateSpan
transpose_ :: ReportOpts -> Bool
..} =
TableOpts
-> (CommandDoc -> Cell)
-> (CommandDoc -> Cell)
-> (MixedAmount -> Cell)
-> Table CommandDoc CommandDoc MixedAmount
-> CommandDoc
forall rh ch a.
TableOpts
-> (rh -> Cell)
-> (ch -> Cell)
-> (a -> Cell)
-> Table rh ch a
-> CommandDoc
T.renderTable TableOpts
forall a. Default a => a
def{tableBorders :: Bool
tableBorders=Bool
False, prettyTable :: Bool
prettyTable=Bool
pretty_tables_}
(Align -> CommandDoc -> Cell
T.alignCell Align
TopLeft) (Align -> CommandDoc -> Cell
T.alignCell Align
TopRight) MixedAmount -> Cell
showamt
where
showamt :: MixedAmount -> Cell
showamt = Align -> [(CommandDoc, Int)] -> Cell
Cell Align
TopRight ([(CommandDoc, Int)] -> Cell)
-> (MixedAmount -> [(CommandDoc, Int)]) -> MixedAmount -> Cell
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CommandDoc, Int) -> [(CommandDoc, Int)]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((CommandDoc, Int) -> [(CommandDoc, Int)])
-> (MixedAmount -> (CommandDoc, Int))
-> MixedAmount
-> [(CommandDoc, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Amount -> CommandDoc)
-> Maybe Int
-> Maybe Int
-> Bool
-> MixedAmount
-> (CommandDoc, Int)
showMixedOneLine Amount -> CommandDoc
showAmountWithoutPrice Maybe Int
forall a. Maybe a
Nothing Maybe Int
mmax Bool
color_
mmax :: Maybe Int
mmax = if Bool
no_elide_ then Maybe Int
forall a. Maybe a
Nothing else Int -> Maybe Int
forall a. a -> Maybe a
Just Int
32
tests_Balance :: TestTree
tests_Balance = CommandDoc -> [TestTree] -> TestTree
tests CommandDoc
"Balance" [
CommandDoc -> [TestTree] -> TestTree
tests CommandDoc
"balanceReportAsText" [
CommandDoc -> IO () -> TestTree
test CommandDoc
"unicode in balance layout" (IO () -> TestTree) -> IO () -> TestTree
forall a b. (a -> b) -> a -> b
$ do
Journal
j <- Text -> IO Journal
readJournal' Text
"2009/01/01 * медвежья шкура\n расходы:покупки 100\n актив:наличные\n"
let rspec :: ReportSpec
rspec = ReportSpec
defreportspec
ReportOpts -> BalanceReport -> CommandDoc
balanceReportAsText (ReportSpec -> ReportOpts
rsOpts ReportSpec
rspec) (ReportSpec -> Journal -> BalanceReport
balanceReport ReportSpec
rspec{rsToday :: Day
rsToday=Integer -> Int -> Int -> Day
fromGregorian Integer
2008 Int
11 Int
26} Journal
j)
CommandDoc -> CommandDoc -> IO ()
forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
@?=
[CommandDoc] -> CommandDoc
unlines
[CommandDoc
" -100 актив:наличные"
,CommandDoc
" 100 расходы:покупки"
,CommandDoc
"--------------------"
,CommandDoc
" 0"
]
]
]