{-# LANGUAGE ExtendedDefaultRules #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
module Hledger.Cli.Commands.Balance (
balancemode
,balance
,balanceReportAsText
,balanceReportAsCsv
,balanceReportItemAsText
,multiBalanceRowAsCsvText
,multiBalanceRowAsTableText
,multiBalanceReportAsText
,multiBalanceReportAsCsv
,multiBalanceReportAsHtml
,multiBalanceReportHtmlRows
,multiBalanceReportHtmlFootRow
,balanceReportAsTable
,balanceReportTableAsText
,tests_Balance
) where
import Data.Default (def)
import Data.List (transpose, foldl', transpose)
import qualified Data.Map as M
import qualified Data.Set as S
import Data.Maybe (fromMaybe)
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Builder as TB
import Data.Time (fromGregorian)
import System.Console.CmdArgs.Explicit as C
import Lucid as L
import Safe (headMay, maximumMay)
import Text.Tabular.AsciiWide
(Align(..), Cell(..), Table(..), TableOpts(..), cellWidth, concatTables,
renderColumns, renderRowB, textCell)
import qualified Text.Tabular.AsciiWide as Tab
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
"sum"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"sum")
CommandDoc
"show sum of posting amounts (default)"
,CommandDoc
-> [CommandDoc]
-> Update RawOpts
-> CommandDoc
-> CommandDoc
-> Flag RawOpts
forall a.
CommandDoc
-> [CommandDoc] -> Update a -> CommandDoc -> CommandDoc -> Flag a
flagOpt CommandDoc
"" [CommandDoc
"budget"] (\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
"budget" CommandDoc
s RawOpts
opts) CommandDoc
"DESCPAT"
([CommandDoc] -> CommandDoc
unlines
[ CommandDoc
"show sum of posting amounts together with budget goals defined by periodic"
, CommandDoc
"transactions. With a DESCPAT argument (must be separated by = not space),"
, CommandDoc
"use only periodic transactions with matching description"
, CommandDoc
"(case insensitive substring match)."
])
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"valuechange"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"valuechange")
CommandDoc
"show total change of value of period-end historical balances (caused by deposits, withdrawals, market price fluctuations)"
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"gain"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"gain")
CommandDoc
"show unrealised capital gain/loss (historical balance value minus cost basis)"
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"change"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"change")
CommandDoc
"accumulate amounts from column start to column end (in multicolumn reports, 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
"accumulate amounts from report start (specified by e.g. -b/--begin) to column end"
,[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
"accumulate amounts from journal start to column end (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
"declared"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"declared") CommandDoc
"include non-parent declared accounts (best used with -E)"
,[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
"related",CommandDoc
"r"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"related") CommandDoc
"show postings' siblings instead"
,[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)"
,[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
"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]
-> Update RawOpts -> CommandDoc -> CommandDoc -> Flag RawOpts
forall a.
[CommandDoc] -> Update a -> CommandDoc -> CommandDoc -> Flag a
flagReq [CommandDoc
"layout"] (\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
"layout" CommandDoc
s RawOpts
opts) CommandDoc
"ARG"
([CommandDoc] -> CommandDoc
unlines
[CommandDoc
"how to show multi-commodity amounts:"
,CommandDoc
"'wide[,WIDTH]': all commodities on one line"
,CommandDoc
"'tall' : each commodity on a new line"
,CommandDoc
"'bare' : bare numbers, symbols in a column"
])
,[CommandDoc] -> Flag RawOpts
outputFormatFlag [CommandDoc
"txt",CommandDoc
"html",CommandDoc
"csv",CommandDoc
"json"]
,Flag RawOpts
outputFileFlag
]
)
[(CommandDoc, [Flag RawOpts])
generalflagsgroup1]
([Flag RawOpts]
hiddenflags [Flag RawOpts] -> [Flag RawOpts] -> [Flag RawOpts]
forall a. [a] -> [a] -> [a]
++
[ [CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone [CommandDoc
"commodity-column"] (CommandDoc -> RawOpts -> RawOpts
setboolopt CommandDoc
"commodity-column")
CommandDoc
"show commodity symbols in a separate column, amounts as bare numbers, one row per commodity"
])
([], 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{reportspec_ :: CliOpts -> ReportSpec
reportspec_=ReportSpec
rspec} Journal
j = case BalanceCalculation
balancecalc_ of
BalanceCalculation
CalcBudget -> do
let reportspan :: DateSpan
reportspan = Journal -> ReportSpec -> DateSpan
reportSpan Journal
j ReportSpec
rspec
budgetreport :: BudgetReport
budgetreport = ReportSpec -> BalancingOpts -> DateSpan -> Journal -> BudgetReport
budgetReport ReportSpec
rspec (InputOpts -> BalancingOpts
balancingopts_ (InputOpts -> BalancingOpts) -> InputOpts -> BalancingOpts
forall a b. (a -> b) -> a -> b
$ CliOpts -> InputOpts
inputopts_ CliOpts
opts) DateSpan
reportspan Journal
j
render :: BudgetReport -> Text
render = case CommandDoc
fmt of
CommandDoc
"txt" -> ReportOpts -> BudgetReport -> Text
budgetReportAsText ReportOpts
ropts
CommandDoc
"json" -> (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>Text
"\n") (Text -> Text) -> (BudgetReport -> Text) -> BudgetReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BudgetReport -> Text
forall a. ToJSON a => a -> Text
toJsonText
CommandDoc
"csv" -> CSV -> Text
printCSV (CSV -> Text) -> (BudgetReport -> CSV) -> BudgetReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> BudgetReport -> CSV
budgetReportAsCsv ReportOpts
ropts
CommandDoc
_ -> CommandDoc -> BudgetReport -> Text
forall a. CommandDoc -> a
error' (CommandDoc -> BudgetReport -> Text)
-> CommandDoc -> BudgetReport -> Text
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc
unsupportedOutputFormatError CommandDoc
fmt
CliOpts -> Text -> IO ()
writeOutputLazyText CliOpts
opts (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ BudgetReport -> Text
render BudgetReport
budgetreport
BalanceCalculation
_ | Bool
multiperiod -> do
let report :: MultiBalanceReport
report = ReportSpec -> Journal -> MultiBalanceReport
multiBalanceReport ReportSpec
rspec Journal
j
render :: MultiBalanceReport -> Text
render = case CommandDoc
fmt of
CommandDoc
"txt" -> ReportOpts -> MultiBalanceReport -> Text
multiBalanceReportAsText ReportOpts
ropts
CommandDoc
"csv" -> CSV -> Text
printCSV (CSV -> Text)
-> (MultiBalanceReport -> CSV) -> MultiBalanceReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> MultiBalanceReport -> CSV
multiBalanceReportAsCsv ReportOpts
ropts
CommandDoc
"html" -> (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>Text
"\n") (Text -> Text)
-> (MultiBalanceReport -> Text) -> MultiBalanceReport -> Text
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" -> (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>Text
"\n") (Text -> Text)
-> (MultiBalanceReport -> Text) -> MultiBalanceReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MultiBalanceReport -> Text
forall a. ToJSON a => a -> Text
toJsonText
CommandDoc
_ -> Text -> MultiBalanceReport -> Text
forall a b. a -> b -> a
const (Text -> MultiBalanceReport -> Text)
-> Text -> MultiBalanceReport -> Text
forall a b. (a -> b) -> a -> b
$ CommandDoc -> Text
forall a. CommandDoc -> a
error' (CommandDoc -> Text) -> CommandDoc -> Text
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc
unsupportedOutputFormatError CommandDoc
fmt
CliOpts -> Text -> IO ()
writeOutputLazyText CliOpts
opts (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ MultiBalanceReport -> Text
render MultiBalanceReport
report
BalanceCalculation
_ -> do
let report :: BalanceReport
report = ReportSpec -> Journal -> BalanceReport
balanceReport ReportSpec
rspec Journal
j
render :: ReportOpts -> BalanceReport -> Text
render = case CommandDoc
fmt of
CommandDoc
"txt" -> \ReportOpts
ropts -> Builder -> Text
TB.toLazyText (Builder -> Text)
-> (BalanceReport -> Builder) -> BalanceReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> BalanceReport -> Builder
balanceReportAsText ReportOpts
ropts
CommandDoc
"csv" -> \ReportOpts
ropts -> CSV -> Text
printCSV (CSV -> Text) -> (BalanceReport -> CSV) -> BalanceReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> BalanceReport -> CSV
balanceReportAsCsv ReportOpts
ropts
CommandDoc
"json" -> (BalanceReport -> Text) -> ReportOpts -> BalanceReport -> Text
forall a b. a -> b -> a
const ((BalanceReport -> Text) -> ReportOpts -> BalanceReport -> Text)
-> (BalanceReport -> Text) -> ReportOpts -> BalanceReport -> Text
forall a b. (a -> b) -> a -> b
$ (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>Text
"\n") (Text -> Text) -> (BalanceReport -> Text) -> BalanceReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BalanceReport -> Text
forall a. ToJSON a => a -> Text
toJsonText
CommandDoc
_ -> CommandDoc -> ReportOpts -> BalanceReport -> Text
forall a. CommandDoc -> a
error' (CommandDoc -> ReportOpts -> BalanceReport -> Text)
-> CommandDoc -> ReportOpts -> BalanceReport -> Text
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc
unsupportedOutputFormatError CommandDoc
fmt
CliOpts -> Text -> IO ()
writeOutputLazyText CliOpts
opts (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ ReportOpts -> BalanceReport -> Text
render ReportOpts
ropts BalanceReport
report
where
ropts :: ReportOpts
ropts@ReportOpts{Bool
Int
[Text]
[Status]
Maybe Int
Maybe Text
Maybe ValuationType
Maybe NormalSign
BalanceCalculation
BalanceAccumulation
AccountListMode
CommodityLayout
Costing
StringFormat
Period
Interval
period_ :: ReportOpts -> Period
interval_ :: ReportOpts -> Interval
statuses_ :: ReportOpts -> [Status]
cost_ :: ReportOpts -> Costing
value_ :: ReportOpts -> Maybe ValuationType
infer_prices_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
date2_ :: ReportOpts -> Bool
empty_ :: ReportOpts -> Bool
no_elide_ :: ReportOpts -> Bool
real_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
average_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
balancecalc_ :: ReportOpts -> BalanceCalculation
balanceaccum_ :: ReportOpts -> BalanceAccumulation
budgetpat_ :: ReportOpts -> Maybe Text
accountlistmode_ :: ReportOpts -> AccountListMode
drop_ :: ReportOpts -> Int
declared_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
percent_ :: ReportOpts -> Bool
invert_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
color_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
commodity_layout_ :: ReportOpts -> CommodityLayout
commodity_layout_ :: CommodityLayout
transpose_ :: Bool
color_ :: Bool
normalbalance_ :: Maybe NormalSign
invert_ :: Bool
percent_ :: Bool
sort_amount_ :: Bool
show_costs_ :: Bool
no_total_ :: Bool
row_total_ :: Bool
declared_ :: Bool
drop_ :: Int
accountlistmode_ :: AccountListMode
budgetpat_ :: Maybe Text
balanceaccum_ :: BalanceAccumulation
txn_dates_ :: Bool
related_ :: Bool
average_ :: Bool
querystring_ :: [Text]
pretty_ :: Bool
format_ :: StringFormat
real_ :: Bool
no_elide_ :: Bool
empty_ :: Bool
date2_ :: Bool
depth_ :: Maybe Int
infer_prices_ :: Bool
value_ :: Maybe ValuationType
cost_ :: Costing
statuses_ :: [Status]
interval_ :: Interval
period_ :: Period
balancecalc_ :: BalanceCalculation
..} = ReportSpec -> ReportOpts
_rsReportOpts ReportSpec
rspec
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
balanceReportAsCsv :: ReportOpts -> BalanceReport -> CSV
balanceReportAsCsv :: ReportOpts -> BalanceReport -> CSV
balanceReportAsCsv ReportOpts
opts ([BalanceReportItem]
items, MixedAmount
total) =
(Text
"account" Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: ((if ReportOpts -> CommodityLayout
commodity_layout_ ReportOpts
opts CommodityLayout -> CommodityLayout -> Bool
forall a. Eq a => a -> a -> Bool
== CommodityLayout
CommodityBare then (:) Text
"commodity" else [Text] -> [Text]
forall a. a -> a
id) ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text
"balance"]))
[Text] -> CSV -> CSV
forall a. a -> [a] -> [a]
: ((BalanceReportItem -> CSV) -> [BalanceReportItem] -> CSV
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(Text
a, Text
_, Int
_, MixedAmount
b) -> Text -> MixedAmount -> CSV
rows Text
a MixedAmount
b) [BalanceReportItem]
items)
CSV -> CSV -> CSV
forall a. [a] -> [a] -> [a]
++ if ReportOpts -> Bool
no_total_ ReportOpts
opts then [] else Text -> MixedAmount -> CSV
rows Text
"total" MixedAmount
total
where
rows :: AccountName -> MixedAmount -> [[T.Text]]
rows :: Text -> MixedAmount -> CSV
rows Text
name MixedAmount
ma = case ReportOpts -> CommodityLayout
commodity_layout_ ReportOpts
opts of
CommodityLayout
CommodityBare ->
((Text, Amount) -> [Text]) -> [(Text, Amount)] -> CSV
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Text
k, Amount
a) -> [Text -> Text
showName Text
name, Text
k, MixedAmount -> Text
renderAmount (MixedAmount -> Text) -> (Amount -> MixedAmount) -> Amount -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Amount -> MixedAmount
mixedAmount (Amount -> MixedAmount)
-> (Amount -> Amount) -> Amount -> MixedAmount
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Amount -> Amount
amountStripPrices (Amount -> Text) -> Amount -> Text
forall a b. (a -> b) -> a -> b
$ Amount
a])
([(Text, Amount)] -> CSV)
-> (MixedAmount -> [(Text, Amount)]) -> MixedAmount -> CSV
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map Text Amount -> [(Text, Amount)]
forall k a. Map k a -> [(k, a)]
M.toList (Map Text Amount -> [(Text, Amount)])
-> (MixedAmount -> Map Text Amount)
-> MixedAmount
-> [(Text, Amount)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map Text Amount -> Amount -> Map Text Amount)
-> Map Text Amount -> [Amount] -> Map Text Amount
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Map Text Amount -> Amount -> Map Text Amount
sumAmounts Map Text Amount
forall a. Monoid a => a
mempty ([Amount] -> Map Text Amount)
-> (MixedAmount -> [Amount]) -> MixedAmount -> Map Text Amount
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MixedAmount -> [Amount]
amounts (MixedAmount -> CSV) -> MixedAmount -> CSV
forall a b. (a -> b) -> a -> b
$ MixedAmount
ma
CommodityLayout
_ -> [[Text -> Text
showName Text
name, MixedAmount -> Text
renderAmount MixedAmount
ma]]
showName :: Text -> Text
showName = Int -> Text -> Text
accountNameDrop (ReportOpts -> Int
drop_ ReportOpts
opts)
renderAmount :: MixedAmount -> Text
renderAmount MixedAmount
amt = WideBuilder -> Text
wbToText (WideBuilder -> Text) -> WideBuilder -> Text
forall a b. (a -> b) -> a -> b
$ AmountDisplayOpts -> MixedAmount -> WideBuilder
showMixedAmountB AmountDisplayOpts
bopts MixedAmount
amt
where bopts :: AmountDisplayOpts
bopts = (Bool -> ReportOpts -> AmountDisplayOpts
balanceOpts Bool
False ReportOpts
opts){displayOrder :: Maybe [Text]
displayOrder = Maybe [Text]
order}
order :: Maybe [Text]
order = if ReportOpts -> CommodityLayout
commodity_layout_ ReportOpts
opts CommodityLayout -> CommodityLayout -> Bool
forall a. Eq a => a -> a -> Bool
== CommodityLayout
CommodityBare then [Text] -> Maybe [Text]
forall a. a -> Maybe a
Just (Set Text -> [Text]
forall a. Set a -> [a]
S.toList (Set Text -> [Text]) -> Set Text -> [Text]
forall a b. (a -> b) -> a -> b
$ MixedAmount -> Set Text
maCommodities MixedAmount
amt) else Maybe [Text]
forall a. Maybe a
Nothing
sumAmounts :: Map Text Amount -> Amount -> Map Text Amount
sumAmounts Map Text Amount
mp Amount
am = (Amount -> Amount -> Amount)
-> Text -> Amount -> Map Text Amount -> Map Text Amount
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
M.insertWith Amount -> Amount -> Amount
forall a. Num a => a -> a -> a
(+) (Amount -> Text
acommodity Amount
am) Amount
am Map Text Amount
mp
balanceReportAsText :: ReportOpts -> BalanceReport -> TB.Builder
balanceReportAsText :: ReportOpts -> BalanceReport -> Builder
balanceReportAsText ReportOpts
opts (([BalanceReportItem]
items, MixedAmount
total)) = case ReportOpts -> CommodityLayout
commodity_layout_ ReportOpts
opts of
CommodityLayout
CommodityBare | Bool
iscustom -> CommandDoc -> Builder
forall a. CommandDoc -> a
error' CommandDoc
"Custom format not supported with commodity columns"
CommodityLayout
CommodityBare -> ReportOpts -> BalanceReport -> Builder
balanceReportAsText' ReportOpts
opts (([BalanceReportItem]
items, MixedAmount
total))
CommodityLayout
_ -> [Builder] -> Builder
unlinesB [Builder]
lines Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> [Builder] -> Builder
unlinesB (if ReportOpts -> Bool
no_total_ ReportOpts
opts then [] else [Builder
overline, Builder
totalLines])
where
([Builder]
lines, [[Int]]
sizes) = [(Builder, [Int])] -> ([Builder], [[Int]])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(Builder, [Int])] -> ([Builder], [[Int]]))
-> [(Builder, [Int])] -> ([Builder], [[Int]])
forall a b. (a -> b) -> a -> b
$ (BalanceReportItem -> (Builder, [Int]))
-> [BalanceReportItem] -> [(Builder, [Int])]
forall a b. (a -> b) -> [a] -> [b]
map (ReportOpts -> BalanceReportItem -> (Builder, [Int])
balanceReportItemAsText ReportOpts
opts) [BalanceReportItem]
items
(Builder
totalLines, [Int]
_) = ReportOpts -> (Text, Int, MixedAmount) -> (Builder, [Int])
renderBalanceReportItem ReportOpts
opts (Text
"",Int
0,MixedAmount
total)
iscustom :: Bool
iscustom = case ReportOpts -> StringFormat
format_ ReportOpts
opts of
OneLine ((FormatField Bool
_ Maybe Int
_ Maybe Int
_ ReportItemField
TotalField):[StringFormatComponent]
_) -> Bool
False
TopAligned ((FormatField Bool
_ Maybe Int
_ Maybe Int
_ ReportItemField
TotalField):[StringFormatComponent]
_) -> Bool
False
BottomAligned ((FormatField Bool
_ Maybe Int
_ Maybe Int
_ ReportItemField
TotalField):[StringFormatComponent]
_) -> Bool
False
StringFormat
_ -> Bool
True
overlinewidth :: Int
overlinewidth = if Bool
iscustom then [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (([Int] -> Int) -> [[Int]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map [Int] -> Int
forall a. Integral a => [a] -> a
maximum' ([[Int]] -> [Int]) -> [[Int]] -> [Int]
forall a b. (a -> b) -> a -> b
$ [[Int]] -> [[Int]]
forall a. [[a]] -> [[a]]
transpose [[Int]]
sizes) else Int
20
overline :: Builder
overline = Text -> Builder
TB.fromText (Text -> Builder) -> Text -> Builder
forall a b. (a -> b) -> a -> b
$ Int -> Text -> Text
T.replicate Int
overlinewidth Text
"-"
balanceReportAsText' :: ReportOpts -> BalanceReport -> TB.Builder
balanceReportAsText' :: ReportOpts -> BalanceReport -> Builder
balanceReportAsText' ReportOpts
opts (([BalanceReportItem]
items, MixedAmount
total)) =
[Builder] -> Builder
unlinesB ([Builder] -> Builder)
-> ([[Cell]] -> [Builder]) -> [[Cell]] -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Cell] -> Builder) -> [[Cell]] -> [Builder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (TableOpts -> [Int] -> Header Cell -> Builder
renderColumns TableOpts
forall a. Default a => a
def{tableBorders :: Bool
tableBorders=Bool
False} [Int]
sizes (Header Cell -> Builder)
-> ([Cell] -> Header Cell) -> [Cell] -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Properties -> [Header Cell] -> Header Cell
forall h. Properties -> [Header h] -> Header h
Tab.Group Properties
Tab.NoLine ([Header Cell] -> Header Cell)
-> ([Cell] -> [Header Cell]) -> [Cell] -> Header Cell
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cell -> Header Cell) -> [Cell] -> [Header Cell]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Cell -> Header Cell
forall h. h -> Header h
Tab.Header) ([[Cell]] -> Builder) -> [[Cell]] -> Builder
forall a b. (a -> b) -> a -> b
$
[[Cell]]
lines [[Cell]] -> [[Cell]] -> [[Cell]]
forall a. [a] -> [a] -> [a]
++ [[[Cell]]] -> [[Cell]]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[[Cell
overline], [Cell]
totalline] | Bool -> Bool
not (ReportOpts -> Bool
no_total_ ReportOpts
opts)]
where
render :: (a, Text, Int, MixedAmount) -> [Cell]
render (a
_, Text
acctname, Int
depth, MixedAmount
amt) =
[ Align -> [WideBuilder] -> Cell
Cell Align
TopRight [WideBuilder]
damts
, Align -> [WideBuilder] -> Cell
Cell Align
TopLeft ((Text -> WideBuilder) -> [Text] -> [WideBuilder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> WideBuilder
wbFromText [Text]
cs)
, Align -> [WideBuilder] -> Cell
Cell Align
TopLeft (Int -> WideBuilder -> [WideBuilder]
forall a. Int -> a -> [a]
replicate ([WideBuilder] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [WideBuilder]
damts Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) WideBuilder
forall a. Monoid a => a
mempty [WideBuilder] -> [WideBuilder] -> [WideBuilder]
forall a. [a] -> [a] -> [a]
++ [Text -> WideBuilder
wbFromText Text
dispname]) ]
where dopts :: AmountDisplayOpts
dopts = (Bool -> ReportOpts -> AmountDisplayOpts
balanceOpts Bool
True ReportOpts
opts){displayOrder :: Maybe [Text]
displayOrder=[Text] -> Maybe [Text]
forall a. a -> Maybe a
Just [Text]
cs}
cs :: [Text]
cs = Set Text -> [Text]
forall a. Set a -> [a]
S.toList (Set Text -> [Text]) -> Set Text -> [Text]
forall a b. (a -> b) -> a -> b
$ MixedAmount -> Set Text
maCommodities MixedAmount
amt
dispname :: Text
dispname = Int -> Text -> Text
T.replicate ((Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
2) Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
acctname
damts :: [WideBuilder]
damts = AmountDisplayOpts -> MixedAmount -> [WideBuilder]
showMixedAmountLinesB AmountDisplayOpts
dopts MixedAmount
amt
lines :: [[Cell]]
lines = (BalanceReportItem -> [Cell]) -> [BalanceReportItem] -> [[Cell]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap BalanceReportItem -> [Cell]
forall a. (a, Text, Int, MixedAmount) -> [Cell]
render [BalanceReportItem]
items
totalline :: [Cell]
totalline = (CommandDoc, Text, Int, MixedAmount) -> [Cell]
forall a. (a, Text, Int, MixedAmount) -> [Cell]
render (CommandDoc
"", Text
"", Int
0, MixedAmount
total)
sizes :: [Int]
sizes = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 (Maybe Int -> Int) -> ([Cell] -> Maybe Int) -> [Cell] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> Maybe Int
forall a. Ord a => [a] -> Maybe a
maximumMay ([Int] -> Maybe Int) -> ([Cell] -> [Int]) -> [Cell] -> Maybe Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cell -> Int) -> [Cell] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Cell -> Int
cellWidth ([Cell] -> Int) -> [[Cell]] -> [Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
[[Cell]] -> [[Cell]]
forall a. [[a]] -> [[a]]
transpose ([[Cell]
totalline | Bool -> Bool
not (ReportOpts -> Bool
no_total_ ReportOpts
opts)] [[Cell]] -> [[Cell]] -> [[Cell]]
forall a. [a] -> [a] -> [a]
++ [[Cell]]
lines)
overline :: Cell
overline = Align -> [WideBuilder] -> Cell
Cell Align
TopLeft ([WideBuilder] -> Cell)
-> (Maybe Int -> [WideBuilder]) -> Maybe Int -> Cell
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WideBuilder -> [WideBuilder]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (WideBuilder -> [WideBuilder])
-> (Maybe Int -> WideBuilder) -> Maybe Int -> [WideBuilder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> WideBuilder
wbFromText (Text -> WideBuilder)
-> (Maybe Int -> Text) -> Maybe Int -> WideBuilder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Text -> Text) -> Text -> Int -> Text
forall a b c. (a -> b -> c) -> b -> a -> c
flip Int -> Text -> Text
T.replicate Text
"-" (Int -> Text) -> (Maybe Int -> Int) -> Maybe Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 (Maybe Int -> Cell) -> Maybe Int -> Cell
forall a b. (a -> b) -> a -> b
$ [Int] -> Maybe Int
forall a. [a] -> Maybe a
headMay [Int]
sizes
balanceReportItemAsText :: ReportOpts -> BalanceReportItem -> (TB.Builder, [Int])
balanceReportItemAsText :: ReportOpts -> BalanceReportItem -> (Builder, [Int])
balanceReportItemAsText ReportOpts
opts (Text
_, Text
accountName, Int
depth, MixedAmount
amt) =
ReportOpts -> (Text, Int, MixedAmount) -> (Builder, [Int])
renderBalanceReportItem ReportOpts
opts (Text
accountName, Int
depth, MixedAmount
amt)
renderBalanceReportItem :: ReportOpts -> (AccountName, Int, MixedAmount) -> (TB.Builder, [Int])
renderBalanceReportItem :: ReportOpts -> (Text, Int, MixedAmount) -> (Builder, [Int])
renderBalanceReportItem ReportOpts
opts (Text
acctname, Int
depth, MixedAmount
total) =
case ReportOpts -> StringFormat
format_ ReportOpts
opts of
OneLine [StringFormatComponent]
comps -> [Cell] -> (Builder, [Int])
renderRow' ([Cell] -> (Builder, [Int])) -> [Cell] -> (Builder, [Int])
forall a b. (a -> b) -> a -> b
$ Bool -> Bool -> [StringFormatComponent] -> [Cell]
render Bool
True Bool
True [StringFormatComponent]
comps
TopAligned [StringFormatComponent]
comps -> [Cell] -> (Builder, [Int])
renderRow' ([Cell] -> (Builder, [Int])) -> [Cell] -> (Builder, [Int])
forall a b. (a -> b) -> a -> b
$ Bool -> Bool -> [StringFormatComponent] -> [Cell]
render Bool
True Bool
False [StringFormatComponent]
comps
BottomAligned [StringFormatComponent]
comps -> [Cell] -> (Builder, [Int])
renderRow' ([Cell] -> (Builder, [Int])) -> [Cell] -> (Builder, [Int])
forall a b. (a -> b) -> a -> b
$ Bool -> Bool -> [StringFormatComponent] -> [Cell]
render Bool
False Bool
False [StringFormatComponent]
comps
where
renderRow' :: [Cell] -> (Builder, [Int])
renderRow' [Cell]
is = ( TableOpts -> Header Cell -> Builder
renderRowB TableOpts
forall a. Default a => a
def{tableBorders :: Bool
tableBorders=Bool
False, borderSpaces :: Bool
borderSpaces=Bool
False}
(Header Cell -> Builder)
-> ([Header Cell] -> Header Cell) -> [Header Cell] -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Properties -> [Header Cell] -> Header Cell
forall h. Properties -> [Header h] -> Header h
Tab.Group Properties
Tab.NoLine ([Header Cell] -> Builder) -> [Header Cell] -> Builder
forall a b. (a -> b) -> a -> b
$ (Cell -> Header Cell) -> [Cell] -> [Header Cell]
forall a b. (a -> b) -> [a] -> [b]
map Cell -> Header Cell
forall h. h -> Header h
Tab.Header [Cell]
is
, (Cell -> Int) -> [Cell] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Cell -> Int
cellWidth [Cell]
is )
render :: Bool -> Bool -> [StringFormatComponent] -> [Cell]
render Bool
topaligned Bool
oneline = (StringFormatComponent -> Cell)
-> [StringFormatComponent] -> [Cell]
forall a b. (a -> b) -> [a] -> [b]
map (Bool
-> Bool
-> ReportOpts
-> (Text, Int, MixedAmount)
-> StringFormatComponent
-> Cell
renderComponent Bool
topaligned Bool
oneline ReportOpts
opts (Text
acctname, Int
depth, MixedAmount
total))
renderComponent :: Bool -> Bool -> ReportOpts -> (AccountName, Int, MixedAmount) -> StringFormatComponent -> Cell
renderComponent :: Bool
-> Bool
-> ReportOpts
-> (Text, Int, MixedAmount)
-> StringFormatComponent
-> Cell
renderComponent Bool
_ Bool
_ ReportOpts
_ (Text, Int, MixedAmount)
_ (FormatLiteral Text
s) = Align -> Text -> Cell
textCell Align
TopLeft Text
s
renderComponent Bool
topaligned Bool
oneline ReportOpts
opts (Text
acctname, Int
depth, MixedAmount
total) (FormatField Bool
ljust Maybe Int
mmin Maybe Int
mmax ReportItemField
field) = case ReportItemField
field of
ReportItemField
DepthSpacerField -> Align -> [WideBuilder] -> Cell
Cell Align
align [Builder -> Int -> WideBuilder
WideBuilder (Text -> Builder
TB.fromText (Text -> Builder) -> Text -> Builder
forall a b. (a -> b) -> a -> b
$ Int -> Text -> Text
T.replicate Int
d Text
" ") Int
d]
where d :: Int
d = (Int -> Int) -> (Int -> Int -> Int) -> Maybe Int -> Int -> Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int -> Int
forall a. a -> a
id Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Maybe Int
mmax (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
1 Maybe Int
mmin
ReportItemField
AccountField -> Align -> Text -> Cell
textCell Align
align (Text -> Cell) -> Text -> Cell
forall a b. (a -> b) -> a -> b
$ Bool -> Maybe Int -> Maybe Int -> Text -> Text
formatText Bool
ljust Maybe Int
mmin Maybe Int
mmax Text
acctname
ReportItemField
TotalField -> Align -> [WideBuilder] -> Cell
Cell Align
align ([WideBuilder] -> Cell)
-> (WideBuilder -> [WideBuilder]) -> WideBuilder -> Cell
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WideBuilder -> [WideBuilder]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (WideBuilder -> Cell) -> WideBuilder -> Cell
forall a b. (a -> b) -> a -> b
$ AmountDisplayOpts -> MixedAmount -> WideBuilder
showMixedAmountB AmountDisplayOpts
dopts MixedAmount
total
ReportItemField
_ -> Align -> [WideBuilder] -> Cell
Cell Align
align [WideBuilder
forall a. Monoid a => a
mempty]
where
align :: Align
align | Bool
topaligned Bool -> Bool -> Bool
&& Bool
ljust = Align
TopLeft
| Bool
topaligned = Align
TopRight
| Bool
ljust = Align
BottomLeft
| Bool
otherwise = Align
BottomRight
dopts :: AmountDisplayOpts
dopts = (Bool -> ReportOpts -> AmountDisplayOpts
balanceOpts Bool
True ReportOpts
opts){displayOneLine :: Bool
displayOneLine=Bool
oneline, displayMinWidth :: Maybe Int
displayMinWidth=Maybe Int
mmin, displayMaxWidth :: Maybe Int
displayMaxWidth=Maybe Int
mmax}
multiBalanceReportAsCsv :: ReportOpts -> MultiBalanceReport -> CSV
multiBalanceReportAsCsv :: ReportOpts -> MultiBalanceReport -> CSV
multiBalanceReportAsCsv opts :: ReportOpts
opts@ReportOpts{Bool
Int
[Text]
[Status]
Maybe Int
Maybe Text
Maybe ValuationType
Maybe NormalSign
BalanceCalculation
BalanceAccumulation
AccountListMode
CommodityLayout
Costing
StringFormat
Period
Interval
commodity_layout_ :: CommodityLayout
transpose_ :: Bool
color_ :: Bool
normalbalance_ :: Maybe NormalSign
invert_ :: Bool
percent_ :: Bool
sort_amount_ :: Bool
show_costs_ :: Bool
no_total_ :: Bool
row_total_ :: Bool
declared_ :: Bool
drop_ :: Int
accountlistmode_ :: AccountListMode
budgetpat_ :: Maybe Text
balanceaccum_ :: BalanceAccumulation
balancecalc_ :: BalanceCalculation
txn_dates_ :: Bool
related_ :: Bool
average_ :: Bool
querystring_ :: [Text]
pretty_ :: Bool
format_ :: StringFormat
real_ :: Bool
no_elide_ :: Bool
empty_ :: Bool
date2_ :: Bool
depth_ :: Maybe Int
infer_prices_ :: Bool
value_ :: Maybe ValuationType
cost_ :: Costing
statuses_ :: [Status]
interval_ :: Interval
period_ :: Period
period_ :: ReportOpts -> Period
interval_ :: ReportOpts -> Interval
statuses_ :: ReportOpts -> [Status]
cost_ :: ReportOpts -> Costing
value_ :: ReportOpts -> Maybe ValuationType
infer_prices_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
date2_ :: ReportOpts -> Bool
empty_ :: ReportOpts -> Bool
no_elide_ :: ReportOpts -> Bool
real_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
average_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
balancecalc_ :: ReportOpts -> BalanceCalculation
balanceaccum_ :: ReportOpts -> BalanceAccumulation
budgetpat_ :: ReportOpts -> Maybe Text
accountlistmode_ :: ReportOpts -> AccountListMode
drop_ :: ReportOpts -> Int
declared_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
percent_ :: ReportOpts -> Bool
invert_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
color_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
commodity_layout_ :: ReportOpts -> CommodityLayout
..} =
(if Bool
transpose_ then CSV -> CSV
forall a. [[a]] -> [[a]]
transpose else CSV -> CSV
forall a. a -> a
id) (CSV -> CSV)
-> (MultiBalanceReport -> CSV) -> MultiBalanceReport -> CSV
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CSV -> CSV -> CSV) -> (CSV, CSV) -> CSV
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry CSV -> CSV -> CSV
forall a. [a] -> [a] -> [a]
(++) ((CSV, CSV) -> CSV)
-> (MultiBalanceReport -> (CSV, CSV)) -> MultiBalanceReport -> CSV
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> MultiBalanceReport -> (CSV, CSV)
multiBalanceReportAsCsv' ReportOpts
opts
multiBalanceReportAsCsv' :: ReportOpts -> MultiBalanceReport -> (CSV, CSV)
multiBalanceReportAsCsv' :: ReportOpts -> MultiBalanceReport -> (CSV, CSV)
multiBalanceReportAsCsv' opts :: ReportOpts
opts@ReportOpts{Bool
Int
[Text]
[Status]
Maybe Int
Maybe Text
Maybe ValuationType
Maybe NormalSign
BalanceCalculation
BalanceAccumulation
AccountListMode
CommodityLayout
Costing
StringFormat
Period
Interval
commodity_layout_ :: CommodityLayout
transpose_ :: Bool
color_ :: Bool
normalbalance_ :: Maybe NormalSign
invert_ :: Bool
percent_ :: Bool
sort_amount_ :: Bool
show_costs_ :: Bool
no_total_ :: Bool
row_total_ :: Bool
declared_ :: Bool
drop_ :: Int
accountlistmode_ :: AccountListMode
budgetpat_ :: Maybe Text
balanceaccum_ :: BalanceAccumulation
balancecalc_ :: BalanceCalculation
txn_dates_ :: Bool
related_ :: Bool
average_ :: Bool
querystring_ :: [Text]
pretty_ :: Bool
format_ :: StringFormat
real_ :: Bool
no_elide_ :: Bool
empty_ :: Bool
date2_ :: Bool
depth_ :: Maybe Int
infer_prices_ :: Bool
value_ :: Maybe ValuationType
cost_ :: Costing
statuses_ :: [Status]
interval_ :: Interval
period_ :: Period
period_ :: ReportOpts -> Period
interval_ :: ReportOpts -> Interval
statuses_ :: ReportOpts -> [Status]
cost_ :: ReportOpts -> Costing
value_ :: ReportOpts -> Maybe ValuationType
infer_prices_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
date2_ :: ReportOpts -> Bool
empty_ :: ReportOpts -> Bool
no_elide_ :: ReportOpts -> Bool
real_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
average_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
balancecalc_ :: ReportOpts -> BalanceCalculation
balanceaccum_ :: ReportOpts -> BalanceAccumulation
budgetpat_ :: ReportOpts -> Maybe Text
accountlistmode_ :: ReportOpts -> AccountListMode
drop_ :: ReportOpts -> Int
declared_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
percent_ :: ReportOpts -> Bool
invert_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
color_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
commodity_layout_ :: ReportOpts -> CommodityLayout
..} (PeriodicReport [DateSpan]
colspans [PeriodicReportRow DisplayName MixedAmount]
items PeriodicReportRow () MixedAmount
tr) =
( (Text
"account" Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text
"commodity" | CommodityLayout
commodity_layout_ CommodityLayout -> CommodityLayout -> Bool
forall a. Eq a => a -> a -> Bool
== CommodityLayout
CommodityBare] [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ (DateSpan -> Text) -> [DateSpan] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map DateSpan -> Text
showDateSpan [DateSpan]
colspans
[Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text
"total" | Bool
row_total_]
[Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text
"average" | Bool
average_]
) [Text] -> CSV -> CSV
forall a. a -> [a] -> [a]
: (PeriodicReportRow DisplayName MixedAmount -> CSV)
-> [PeriodicReportRow DisplayName MixedAmount] -> CSV
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ((PeriodicReportRow DisplayName MixedAmount -> Text)
-> PeriodicReportRow DisplayName MixedAmount -> CSV
forall a.
(PeriodicReportRow a MixedAmount -> Text)
-> PeriodicReportRow a MixedAmount -> CSV
fullRowAsTexts (Int -> Text -> Text
accountNameDrop Int
drop_ (Text -> Text)
-> (PeriodicReportRow DisplayName MixedAmount -> Text)
-> PeriodicReportRow DisplayName MixedAmount
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PeriodicReportRow DisplayName MixedAmount -> Text
forall a. PeriodicReportRow DisplayName a -> Text
prrFullName)) [PeriodicReportRow DisplayName MixedAmount]
items
, CSV
totalrows)
where
fullRowAsTexts :: (PeriodicReportRow a MixedAmount -> Text)
-> PeriodicReportRow a MixedAmount -> CSV
fullRowAsTexts PeriodicReportRow a MixedAmount -> Text
render PeriodicReportRow a MixedAmount
row = (PeriodicReportRow a MixedAmount -> Text
render PeriodicReportRow a MixedAmount
row Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:) ([Text] -> [Text]) -> CSV -> CSV
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReportOpts -> PeriodicReportRow a MixedAmount -> CSV
forall a. ReportOpts -> PeriodicReportRow a MixedAmount -> CSV
multiBalanceRowAsCsvText ReportOpts
opts PeriodicReportRow a MixedAmount
row
totalrows :: CSV
totalrows
| Bool
no_total_ = CSV
forall a. Monoid a => a
mempty
| Bool
otherwise = (PeriodicReportRow () MixedAmount -> Text)
-> PeriodicReportRow () MixedAmount -> CSV
forall a.
(PeriodicReportRow a MixedAmount -> Text)
-> PeriodicReportRow a MixedAmount -> CSV
fullRowAsTexts (Text -> PeriodicReportRow () MixedAmount -> Text
forall a b. a -> b -> a
const Text
"total") PeriodicReportRow () MixedAmount
tr
multiBalanceReportAsHtml :: ReportOpts -> MultiBalanceReport -> Html ()
multiBalanceReportAsHtml :: ReportOpts -> MultiBalanceReport -> Html ()
multiBalanceReportAsHtml ReportOpts
ropts MultiBalanceReport
mbr =
let
(Html ()
headingsrow,[Html ()]
bodyrows,[Html ()]
mtotalsrows) = ReportOpts -> MultiBalanceReport -> (Html (), [Html ()], [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]
++ [Html ()]
mtotalsrows
multiBalanceReportHtmlRows :: ReportOpts -> MultiBalanceReport -> (Html (), [Html ()], [Html ()])
multiBalanceReportHtmlRows :: ReportOpts -> MultiBalanceReport -> (Html (), [Html ()], [Html ()])
multiBalanceReportHtmlRows ReportOpts
ropts MultiBalanceReport
mbr =
let
([Text]
headingsrow:CSV
bodyrows, CSV
mtotalsrows)
| ReportOpts -> Bool
transpose_ ReportOpts
ropts = CommandDoc -> (CSV, CSV)
forall a. CommandDoc -> a
error' CommandDoc
"Sorry, --transpose with HTML output is not yet supported"
| Bool
otherwise = ReportOpts -> MultiBalanceReport -> (CSV, CSV)
multiBalanceReportAsCsv' ReportOpts
ropts MultiBalanceReport
mbr
in
(ReportOpts -> [Text] -> Html ()
multiBalanceReportHtmlHeadRow ReportOpts
ropts [Text]
headingsrow
,([Text] -> Html ()) -> CSV -> [Html ()]
forall a b. (a -> b) -> [a] -> [b]
map (ReportOpts -> [Text] -> Html ()
multiBalanceReportHtmlBodyRow ReportOpts
ropts) CSV
bodyrows
,ReportOpts -> [Text] -> Html ()
multiBalanceReportHtmlFootRow ReportOpts
ropts ([Text] -> Html ()) -> CSV -> [Html ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CSV
mtotalsrows
)
multiBalanceReportHtmlHeadRow :: ReportOpts -> [T.Text] -> Html ()
multiBalanceReportHtmlHeadRow :: ReportOpts -> [Text] -> Html ()
multiBalanceReportHtmlHeadRow ReportOpts
_ [] = Html ()
forall a. Monoid a => a
mempty
multiBalanceReportHtmlHeadRow ReportOpts
ropts (Text
acct:[Text]
rest) =
let
defstyle :: Attribute
defstyle = Text -> Attribute
forall arg result. TermRaw arg result => arg -> result
style_ Text
""
([Text]
amts,[Text]
tot,[Text]
avg)
| ReportOpts -> Bool
row_total_ ReportOpts
ropts Bool -> Bool -> Bool
&& ReportOpts -> Bool
average_ ReportOpts
ropts = ([Text] -> [Text]
forall a. [a] -> [a]
init ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
forall a. [a] -> [a]
init [Text]
rest, [[Text] -> Text
forall a. [a] -> a
last ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
forall a. [a] -> [a]
init [Text]
rest], [[Text] -> Text
forall a. [a] -> a
last [Text]
rest])
| ReportOpts -> Bool
row_total_ ReportOpts
ropts = ([Text] -> [Text]
forall a. [a] -> [a]
init [Text]
rest, [[Text] -> Text
forall a. [a] -> a
last [Text]
rest], [])
| ReportOpts -> Bool
average_ ReportOpts
ropts = ([Text] -> [Text]
forall a. [a] -> [a]
init [Text]
rest, [], [[Text] -> Text
forall a. [a] -> a
last [Text]
rest])
| Bool
otherwise = ([Text]
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 -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml Text
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] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml Text
a) | Text
a <- [Text]
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] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml Text
a) | Text
a <- [Text]
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] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml Text
a) | Text
a <- [Text]
avg]
multiBalanceReportHtmlBodyRow :: ReportOpts -> [T.Text] -> Html ()
multiBalanceReportHtmlBodyRow :: ReportOpts -> [Text] -> Html ()
multiBalanceReportHtmlBodyRow ReportOpts
_ [] = Html ()
forall a. Monoid a => a
mempty
multiBalanceReportHtmlBodyRow ReportOpts
ropts (Text
label:[Text]
rest) =
let
defstyle :: Attribute
defstyle = Text -> Attribute
forall arg result. TermRaw arg result => arg -> result
style_ Text
"text-align:right"
([Text]
amts,[Text]
tot,[Text]
avg)
| ReportOpts -> Bool
row_total_ ReportOpts
ropts Bool -> Bool -> Bool
&& ReportOpts -> Bool
average_ ReportOpts
ropts = ([Text] -> [Text]
forall a. [a] -> [a]
init ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
forall a. [a] -> [a]
init [Text]
rest, [[Text] -> Text
forall a. [a] -> a
last ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
forall a. [a] -> [a]
init [Text]
rest], [[Text] -> Text
forall a. [a] -> a
last [Text]
rest])
| ReportOpts -> Bool
row_total_ ReportOpts
ropts = ([Text] -> [Text]
forall a. [a] -> [a]
init [Text]
rest, [[Text] -> Text
forall a. [a] -> a
last [Text]
rest], [])
| ReportOpts -> Bool
average_ ReportOpts
ropts = ([Text] -> [Text]
forall a. [a] -> [a]
init [Text]
rest, [], [[Text] -> Text
forall a. [a] -> a
last [Text]
rest])
| Bool
otherwise = ([Text]
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"] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml Text
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] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml Text
a) | Text
a <- [Text]
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] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml Text
a) | Text
a <- [Text]
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] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml Text
a) | Text
a <- [Text]
avg]
multiBalanceReportHtmlFootRow :: ReportOpts -> [T.Text] -> Html ()
ReportOpts
_ropts [] = Html ()
forall a. Monoid a => a
mempty
multiBalanceReportHtmlFootRow ReportOpts
ropts (Text
acct:[Text]
rest) =
let
defstyle :: Attribute
defstyle = Text -> Attribute
forall arg result. TermRaw arg result => arg -> result
style_ Text
"text-align:right"
([Text]
amts,[Text]
tot,[Text]
avg)
| ReportOpts -> Bool
row_total_ ReportOpts
ropts Bool -> Bool -> Bool
&& ReportOpts -> Bool
average_ ReportOpts
ropts = ([Text] -> [Text]
forall a. [a] -> [a]
init ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
forall a. [a] -> [a]
init [Text]
rest, [[Text] -> Text
forall a. [a] -> a
last ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
forall a. [a] -> [a]
init [Text]
rest], [[Text] -> Text
forall a. [a] -> a
last [Text]
rest])
| ReportOpts -> Bool
row_total_ ReportOpts
ropts = ([Text] -> [Text]
forall a. [a] -> [a]
init [Text]
rest, [[Text] -> Text
forall a. [a] -> a
last [Text]
rest], [])
| ReportOpts -> Bool
average_ ReportOpts
ropts = ([Text] -> [Text]
forall a. [a] -> [a]
init [Text]
rest, [], [[Text] -> Text
forall a. [a] -> a
last [Text]
rest])
| Bool
otherwise = ([Text]
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"] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml Text
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] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml Text
a) | Text
a <- [Text]
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] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml Text
a) | Text
a <- [Text]
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] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml Text
a) | Text
a <- [Text]
avg]
multiBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> TL.Text
multiBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> Text
multiBalanceReportAsText ropts :: ReportOpts
ropts@ReportOpts{Bool
Int
[Text]
[Status]
Maybe Int
Maybe Text
Maybe ValuationType
Maybe NormalSign
BalanceCalculation
BalanceAccumulation
AccountListMode
CommodityLayout
Costing
StringFormat
Period
Interval
commodity_layout_ :: CommodityLayout
transpose_ :: Bool
color_ :: Bool
normalbalance_ :: Maybe NormalSign
invert_ :: Bool
percent_ :: Bool
sort_amount_ :: Bool
show_costs_ :: Bool
no_total_ :: Bool
row_total_ :: Bool
declared_ :: Bool
drop_ :: Int
accountlistmode_ :: AccountListMode
budgetpat_ :: Maybe Text
balanceaccum_ :: BalanceAccumulation
balancecalc_ :: BalanceCalculation
txn_dates_ :: Bool
related_ :: Bool
average_ :: Bool
querystring_ :: [Text]
pretty_ :: Bool
format_ :: StringFormat
real_ :: Bool
no_elide_ :: Bool
empty_ :: Bool
date2_ :: Bool
depth_ :: Maybe Int
infer_prices_ :: Bool
value_ :: Maybe ValuationType
cost_ :: Costing
statuses_ :: [Status]
interval_ :: Interval
period_ :: Period
period_ :: ReportOpts -> Period
interval_ :: ReportOpts -> Interval
statuses_ :: ReportOpts -> [Status]
cost_ :: ReportOpts -> Costing
value_ :: ReportOpts -> Maybe ValuationType
infer_prices_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
date2_ :: ReportOpts -> Bool
empty_ :: ReportOpts -> Bool
no_elide_ :: ReportOpts -> Bool
real_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
average_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
balancecalc_ :: ReportOpts -> BalanceCalculation
balanceaccum_ :: ReportOpts -> BalanceAccumulation
budgetpat_ :: ReportOpts -> Maybe Text
accountlistmode_ :: ReportOpts -> AccountListMode
drop_ :: ReportOpts -> Int
declared_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
percent_ :: ReportOpts -> Bool
invert_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
color_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
commodity_layout_ :: ReportOpts -> CommodityLayout
..} MultiBalanceReport
r = Builder -> Text
TB.toLazyText (Builder -> Text) -> Builder -> Text
forall a b. (a -> b) -> a -> b
$
Text -> Builder
TB.fromText Text
title
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
TB.fromText Text
"\n\n"
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ReportOpts -> Table Text Text WideBuilder -> Builder
balanceReportTableAsText ReportOpts
ropts (ReportOpts -> MultiBalanceReport -> Table Text Text WideBuilder
balanceReportAsTable ReportOpts
ropts MultiBalanceReport
r)
where
title :: Text
title = Text
mtitle Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" in " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> DateSpan -> Text
showDateSpan (MultiBalanceReport -> DateSpan
forall a b. PeriodicReport a b -> DateSpan
periodicReportSpan MultiBalanceReport
r) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
valuationdesc Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
":"
mtitle :: Text
mtitle = case (BalanceCalculation
balancecalc_, BalanceAccumulation
balanceaccum_) of
(BalanceCalculation
CalcValueChange, BalanceAccumulation
PerPeriod ) -> Text
"Period-end value changes"
(BalanceCalculation
CalcValueChange, BalanceAccumulation
Cumulative ) -> Text
"Cumulative period-end value changes"
(BalanceCalculation
CalcGain, BalanceAccumulation
PerPeriod ) -> Text
"Incremental gain"
(BalanceCalculation
CalcGain, BalanceAccumulation
Cumulative ) -> Text
"Cumulative gain"
(BalanceCalculation
CalcGain, BalanceAccumulation
Historical ) -> Text
"Historical gain"
(BalanceCalculation
_, BalanceAccumulation
PerPeriod ) -> Text
"Balance changes"
(BalanceCalculation
_, BalanceAccumulation
Cumulative ) -> Text
"Ending balances (cumulative)"
(BalanceCalculation
_, BalanceAccumulation
Historical) -> Text
"Ending balances (historical)"
valuationdesc :: Text
valuationdesc =
(case Costing
cost_ of
Costing
Cost -> Text
", converted to cost"
Costing
NoCost -> Text
"")
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (case Maybe ValuationType
value_ of
Just (AtThen Maybe Text
_mc) -> Text
", valued at posting date"
Just (AtEnd Maybe Text
_mc) | Bool
changingValuation -> Text
""
Just (AtEnd Maybe Text
_mc) -> Text
", valued at period ends"
Just (AtNow Maybe Text
_mc) -> Text
", current value"
Just (AtDate Day
d Maybe Text
_mc) -> Text
", valued at " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Day -> Text
showDate Day
d
Maybe ValuationType
Nothing -> Text
"")
changingValuation :: Bool
changingValuation = case (BalanceCalculation
balancecalc_, BalanceAccumulation
balanceaccum_) of
(BalanceCalculation
CalcValueChange, BalanceAccumulation
PerPeriod) -> Bool
True
(BalanceCalculation
CalcValueChange, BalanceAccumulation
Cumulative) -> Bool
True
(BalanceCalculation, BalanceAccumulation)
_ -> Bool
False
balanceReportAsTable :: ReportOpts -> MultiBalanceReport -> Table T.Text T.Text WideBuilder
balanceReportAsTable :: ReportOpts -> MultiBalanceReport -> Table Text Text WideBuilder
balanceReportAsTable opts :: ReportOpts
opts@ReportOpts{Bool
average_ :: Bool
average_ :: ReportOpts -> Bool
average_, Bool
row_total_ :: Bool
row_total_ :: ReportOpts -> Bool
row_total_, BalanceAccumulation
balanceaccum_ :: BalanceAccumulation
balanceaccum_ :: ReportOpts -> BalanceAccumulation
balanceaccum_}
(PeriodicReport [DateSpan]
spans [PeriodicReportRow DisplayName MixedAmount]
items PeriodicReportRow () MixedAmount
tr) =
Table Text Text WideBuilder -> Table Text Text WideBuilder
forall rh a. Table rh rh a -> Table rh rh a
maybetranspose (Table Text Text WideBuilder -> Table Text Text WideBuilder)
-> Table Text Text WideBuilder -> Table Text Text WideBuilder
forall a b. (a -> b) -> a -> b
$
Table Text Text WideBuilder -> Table Text Text WideBuilder
forall ch. Table Text ch WideBuilder -> Table Text ch WideBuilder
addtotalrow (Table Text Text WideBuilder -> Table Text Text WideBuilder)
-> Table Text Text WideBuilder -> Table Text Text WideBuilder
forall a b. (a -> b) -> a -> b
$
Header Text
-> Header Text -> [[WideBuilder]] -> Table Text Text WideBuilder
forall rh ch a. Header rh -> Header ch -> [[a]] -> Table rh ch a
Table
(Properties -> [Header Text] -> Header Text
forall h. Properties -> [Header h] -> Header h
Tab.Group Properties
Tab.NoLine ([Header Text] -> Header Text) -> [Header Text] -> Header Text
forall a b. (a -> b) -> a -> b
$ (Text -> Header Text) -> [Text] -> [Header Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Header Text
forall h. h -> Header h
Tab.Header (CSV -> [Text]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat CSV
accts))
(Properties -> [Header Text] -> Header Text
forall h. Properties -> [Header h] -> Header h
Tab.Group Properties
Tab.NoLine ([Header Text] -> Header Text) -> [Header Text] -> Header Text
forall a b. (a -> b) -> a -> b
$ (Text -> Header Text) -> [Text] -> [Header Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Header Text
forall h. h -> Header h
Tab.Header [Text]
colheadings)
([[[WideBuilder]]] -> [[WideBuilder]]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[[WideBuilder]]]
rows)
where
totalscolumn :: Bool
totalscolumn = Bool
row_total_ Bool -> Bool -> Bool
&& BalanceAccumulation
balanceaccum_ BalanceAccumulation -> [BalanceAccumulation] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [BalanceAccumulation
Cumulative, BalanceAccumulation
Historical]
colheadings :: [Text]
colheadings = [Text
"Commodity" | ReportOpts -> CommodityLayout
commodity_layout_ ReportOpts
opts CommodityLayout -> CommodityLayout -> Bool
forall a. Eq a => a -> a -> Bool
== CommodityLayout
CommodityBare]
[Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ (DateSpan -> Text) -> [DateSpan] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (BalanceAccumulation -> [DateSpan] -> DateSpan -> Text
reportPeriodName BalanceAccumulation
balanceaccum_ [DateSpan]
spans) [DateSpan]
spans
[Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text
" Total" | Bool
totalscolumn]
[Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text
"Average" | Bool
average_]
fullRowAsTexts :: PeriodicReportRow DisplayName MixedAmount
-> ([Text], [[WideBuilder]])
fullRowAsTexts PeriodicReportRow DisplayName MixedAmount
row =
let rs :: [[WideBuilder]]
rs = ReportOpts
-> PeriodicReportRow DisplayName MixedAmount -> [[WideBuilder]]
forall a.
ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
multiBalanceRowAsTableText ReportOpts
opts PeriodicReportRow DisplayName MixedAmount
row
in (Int -> Text -> [Text]
forall a. Int -> a -> [a]
replicate ([[WideBuilder]] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[WideBuilder]]
rs) (PeriodicReportRow DisplayName MixedAmount -> Text
forall a. PeriodicReportRow DisplayName a -> Text
renderacct PeriodicReportRow DisplayName MixedAmount
row), [[WideBuilder]]
rs)
(CSV
accts, [[[WideBuilder]]]
rows) = [([Text], [[WideBuilder]])] -> (CSV, [[[WideBuilder]]])
forall a b. [(a, b)] -> ([a], [b])
unzip ([([Text], [[WideBuilder]])] -> (CSV, [[[WideBuilder]]]))
-> [([Text], [[WideBuilder]])] -> (CSV, [[[WideBuilder]]])
forall a b. (a -> b) -> a -> b
$ (PeriodicReportRow DisplayName MixedAmount
-> ([Text], [[WideBuilder]]))
-> [PeriodicReportRow DisplayName MixedAmount]
-> [([Text], [[WideBuilder]])]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap PeriodicReportRow DisplayName MixedAmount
-> ([Text], [[WideBuilder]])
fullRowAsTexts [PeriodicReportRow DisplayName MixedAmount]
items
renderacct :: PeriodicReportRow DisplayName a -> Text
renderacct PeriodicReportRow DisplayName a
row =
Int -> Text -> Text
T.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) Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> PeriodicReportRow DisplayName a -> Text
forall a. PeriodicReportRow DisplayName a -> Text
prrDisplayName PeriodicReportRow DisplayName a
row
addtotalrow :: Table Text ch WideBuilder -> Table Text ch WideBuilder
addtotalrow
| ReportOpts -> Bool
no_total_ ReportOpts
opts = Table Text ch WideBuilder -> Table Text ch WideBuilder
forall a. a -> a
id
| Bool
otherwise =
let totalrows :: [[WideBuilder]]
totalrows = ReportOpts -> PeriodicReportRow () MixedAmount -> [[WideBuilder]]
forall a.
ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
multiBalanceRowAsTableText ReportOpts
opts PeriodicReportRow () MixedAmount
tr
rh :: Header Text
rh = Properties -> [Header Text] -> Header Text
forall h. Properties -> [Header h] -> Header h
Tab.Group Properties
Tab.NoLine ([Header Text] -> Header Text)
-> (Header Text -> [Header Text]) -> Header Text -> Header Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Header Text -> [Header Text]
forall a. Int -> a -> [a]
replicate ([[WideBuilder]] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[WideBuilder]]
totalrows) (Header Text -> Header Text) -> Header Text -> Header Text
forall a b. (a -> b) -> a -> b
$ Text -> Header Text
forall h. h -> Header h
Tab.Header Text
""
ch :: Header [a]
ch = [a] -> Header [a]
forall h. h -> Header h
Tab.Header []
in ((Table Text ch WideBuilder
-> Table Text [Any] WideBuilder -> Table Text ch WideBuilder)
-> Table Text [Any] WideBuilder
-> Table Text ch WideBuilder
-> Table Text ch WideBuilder
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Properties
-> Table Text ch WideBuilder
-> Table Text [Any] WideBuilder
-> Table Text ch WideBuilder
forall rh ch a ch2.
Properties -> Table rh ch a -> Table rh ch2 a -> Table rh ch a
concatTables Properties
Tab.SingleLine) (Table Text [Any] WideBuilder
-> Table Text ch WideBuilder -> Table Text ch WideBuilder)
-> Table Text [Any] WideBuilder
-> Table Text ch WideBuilder
-> Table Text ch WideBuilder
forall a b. (a -> b) -> a -> b
$ Header Text
-> Header [Any] -> [[WideBuilder]] -> Table Text [Any] WideBuilder
forall rh ch a. Header rh -> Header ch -> [[a]] -> Table rh ch a
Table Header Text
rh Header [Any]
forall a. Header [a]
ch [[WideBuilder]]
totalrows)
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
multiBalanceRowAsWbs :: AmountDisplayOpts -> ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
multiBalanceRowAsWbs :: AmountDisplayOpts
-> ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
multiBalanceRowAsWbs AmountDisplayOpts
bopts ReportOpts{Bool
Int
[Text]
[Status]
Maybe Int
Maybe Text
Maybe ValuationType
Maybe NormalSign
BalanceCalculation
BalanceAccumulation
AccountListMode
CommodityLayout
Costing
StringFormat
Period
Interval
commodity_layout_ :: CommodityLayout
transpose_ :: Bool
color_ :: Bool
normalbalance_ :: Maybe NormalSign
invert_ :: Bool
percent_ :: Bool
sort_amount_ :: Bool
show_costs_ :: Bool
no_total_ :: Bool
row_total_ :: Bool
declared_ :: Bool
drop_ :: Int
accountlistmode_ :: AccountListMode
budgetpat_ :: Maybe Text
balanceaccum_ :: BalanceAccumulation
balancecalc_ :: BalanceCalculation
txn_dates_ :: Bool
related_ :: Bool
average_ :: Bool
querystring_ :: [Text]
pretty_ :: Bool
format_ :: StringFormat
real_ :: Bool
no_elide_ :: Bool
empty_ :: Bool
date2_ :: Bool
depth_ :: Maybe Int
infer_prices_ :: Bool
value_ :: Maybe ValuationType
cost_ :: Costing
statuses_ :: [Status]
interval_ :: Interval
period_ :: Period
period_ :: ReportOpts -> Period
interval_ :: ReportOpts -> Interval
statuses_ :: ReportOpts -> [Status]
cost_ :: ReportOpts -> Costing
value_ :: ReportOpts -> Maybe ValuationType
infer_prices_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
date2_ :: ReportOpts -> Bool
empty_ :: ReportOpts -> Bool
no_elide_ :: ReportOpts -> Bool
real_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
average_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
balancecalc_ :: ReportOpts -> BalanceCalculation
balanceaccum_ :: ReportOpts -> BalanceAccumulation
budgetpat_ :: ReportOpts -> Maybe Text
accountlistmode_ :: ReportOpts -> AccountListMode
drop_ :: ReportOpts -> Int
declared_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
percent_ :: ReportOpts -> Bool
invert_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
color_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
commodity_layout_ :: ReportOpts -> CommodityLayout
..} (PeriodicReportRow a
_ [MixedAmount]
as MixedAmount
rowtot MixedAmount
rowavg) =
case CommodityLayout
commodity_layout_ of
CommodityWide Maybe Int
width -> [(MixedAmount -> WideBuilder) -> [MixedAmount] -> [WideBuilder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (AmountDisplayOpts -> MixedAmount -> WideBuilder
showMixedAmountB AmountDisplayOpts
bopts{displayMaxWidth :: Maybe Int
displayMaxWidth=Maybe Int
width}) [MixedAmount]
all]
CommodityLayout
CommodityTall -> WideBuilder -> [[WideBuilder]] -> [[WideBuilder]]
forall a. a -> [[a]] -> [[a]]
paddedTranspose WideBuilder
forall a. Monoid a => a
mempty
([[WideBuilder]] -> [[WideBuilder]])
-> ([MixedAmount] -> [[WideBuilder]])
-> [MixedAmount]
-> [[WideBuilder]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MixedAmount -> [WideBuilder]) -> [MixedAmount] -> [[WideBuilder]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (AmountDisplayOpts -> MixedAmount -> [WideBuilder]
showMixedAmountLinesB AmountDisplayOpts
bopts{displayMaxWidth :: Maybe Int
displayMaxWidth=Maybe Int
forall a. Maybe a
Nothing})
([MixedAmount] -> [[WideBuilder]])
-> [MixedAmount] -> [[WideBuilder]]
forall a b. (a -> b) -> a -> b
$ [MixedAmount]
all
CommodityLayout
CommodityBare -> (WideBuilder -> [WideBuilder] -> [WideBuilder])
-> [WideBuilder] -> [[WideBuilder]] -> [[WideBuilder]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (:) ((Text -> WideBuilder) -> [Text] -> [WideBuilder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> WideBuilder
wbFromText [Text]
cs)
([[WideBuilder]] -> [[WideBuilder]])
-> ([MixedAmount] -> [[WideBuilder]])
-> [MixedAmount]
-> [[WideBuilder]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[WideBuilder]] -> [[WideBuilder]]
forall a. [[a]] -> [[a]]
transpose
([[WideBuilder]] -> [[WideBuilder]])
-> ([MixedAmount] -> [[WideBuilder]])
-> [MixedAmount]
-> [[WideBuilder]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MixedAmount -> [WideBuilder]) -> [MixedAmount] -> [[WideBuilder]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (AmountDisplayOpts -> MixedAmount -> [WideBuilder]
showMixedAmountLinesB AmountDisplayOpts
bopts{displayOrder :: Maybe [Text]
displayOrder=[Text] -> Maybe [Text]
forall a. a -> Maybe a
Just [Text]
cs, displayMinWidth :: Maybe Int
displayMinWidth=Maybe Int
forall a. Maybe a
Nothing})
([MixedAmount] -> [[WideBuilder]])
-> [MixedAmount] -> [[WideBuilder]]
forall a b. (a -> b) -> a -> b
$ [MixedAmount]
all
where
totalscolumn :: Bool
totalscolumn = Bool
row_total_ Bool -> Bool -> Bool
&& BalanceAccumulation
balanceaccum_ BalanceAccumulation -> [BalanceAccumulation] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [BalanceAccumulation
Cumulative, BalanceAccumulation
Historical]
cs :: [Text]
cs = Set Text -> [Text]
forall a. Set a -> [a]
S.toList (Set Text -> [Text])
-> ([Set Text] -> Set Text) -> [Set Text] -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Set Text -> Set Text -> Set Text)
-> Set Text -> [Set Text] -> Set Text
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Set Text -> Set Text -> Set Text
forall a. Ord a => Set a -> Set a -> Set a
S.union Set Text
forall a. Monoid a => a
mempty ([Set Text] -> [Text]) -> [Set Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ (MixedAmount -> Set Text) -> [MixedAmount] -> [Set Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap MixedAmount -> Set Text
maCommodities [MixedAmount]
all
all :: [MixedAmount]
all = [MixedAmount]
as
[MixedAmount] -> [MixedAmount] -> [MixedAmount]
forall a. [a] -> [a] -> [a]
++ [MixedAmount
rowtot | Bool
totalscolumn Bool -> Bool -> Bool
&& Bool -> Bool
not ([MixedAmount] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [MixedAmount]
as)]
[MixedAmount] -> [MixedAmount] -> [MixedAmount]
forall a. [a] -> [a] -> [a]
++ [MixedAmount
rowavg | Bool
average_ Bool -> Bool -> Bool
&& Bool -> Bool
not ([MixedAmount] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [MixedAmount]
as)]
paddedTranspose :: a -> [[a]] -> [[a]]
paddedTranspose :: a -> [[a]] -> [[a]]
paddedTranspose a
_ [] = [[]]
paddedTranspose a
n [[a]]
as = Int -> [[a]] -> [[a]]
forall a. Int -> [a] -> [a]
take ([Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Int] -> Int) -> ([[a]] -> [Int]) -> [[a]] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([a] -> Int) -> [[a]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([[a]] -> Int) -> [[a]] -> Int
forall a b. (a -> b) -> a -> b
$ [[a]]
as) ([[a]] -> [[a]]) -> ([[a]] -> [[a]]) -> [[a]] -> [[a]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[a]] -> [[a]]
trans ([[a]] -> [[a]]) -> [[a]] -> [[a]]
forall a b. (a -> b) -> a -> b
$ [[a]]
as
where
trans :: [[a]] -> [[a]]
trans ([] : [[a]]
xss) = (a
n a -> [a] -> [a]
forall a. a -> [a] -> [a]
: ([a] -> a) -> [[a]] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map [a] -> a
h [[a]]
xss) [a] -> [[a]] -> [[a]]
forall a. a -> [a] -> [a]
: [[a]] -> [[a]]
trans ([a
n] [a] -> [[a]] -> [[a]]
forall a. a -> [a] -> [a]
: ([a] -> [a]) -> [[a]] -> [[a]]
forall a b. (a -> b) -> [a] -> [b]
map [a] -> [a]
t [[a]]
xss)
trans ((a
x : [a]
xs) : [[a]]
xss) = (a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: ([a] -> a) -> [[a]] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map [a] -> a
h [[a]]
xss) [a] -> [[a]] -> [[a]]
forall a. a -> [a] -> [a]
: [[a]] -> [[a]]
trans ([a] -> [a]
m [a]
xs [a] -> [[a]] -> [[a]]
forall a. a -> [a] -> [a]
: ([a] -> [a]) -> [[a]] -> [[a]]
forall a b. (a -> b) -> [a] -> [b]
map [a] -> [a]
t [[a]]
xss)
trans [] = []
h :: [a] -> a
h (a
x:[a]
_) = a
x
h [] = a
n
t :: [a] -> [a]
t (a
_:[a]
xs) = [a]
xs
t [] = [a
n]
m :: [a] -> [a]
m (a
x:[a]
xs) = a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
xs
m [] = [a
n]
multiBalanceRowAsCsvText :: ReportOpts -> PeriodicReportRow a MixedAmount -> [[T.Text]]
multiBalanceRowAsCsvText :: ReportOpts -> PeriodicReportRow a MixedAmount -> CSV
multiBalanceRowAsCsvText ReportOpts
opts = ([WideBuilder] -> [Text]) -> [[WideBuilder]] -> CSV
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((WideBuilder -> Text) -> [WideBuilder] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap WideBuilder -> Text
wbToText) ([[WideBuilder]] -> CSV)
-> (PeriodicReportRow a MixedAmount -> [[WideBuilder]])
-> PeriodicReportRow a MixedAmount
-> CSV
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AmountDisplayOpts
-> ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
forall a.
AmountDisplayOpts
-> ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
multiBalanceRowAsWbs (Bool -> ReportOpts -> AmountDisplayOpts
balanceOpts Bool
False ReportOpts
opts) ReportOpts
opts
multiBalanceRowAsTableText :: ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
multiBalanceRowAsTableText :: ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
multiBalanceRowAsTableText ReportOpts
opts = AmountDisplayOpts
-> ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
forall a.
AmountDisplayOpts
-> ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
multiBalanceRowAsWbs (Bool -> ReportOpts -> AmountDisplayOpts
balanceOpts Bool
True ReportOpts
opts) ReportOpts
opts
balanceOpts :: Bool -> ReportOpts -> AmountDisplayOpts
balanceOpts :: Bool -> ReportOpts -> AmountDisplayOpts
balanceOpts Bool
isTable ReportOpts{Bool
Int
[Text]
[Status]
Maybe Int
Maybe Text
Maybe ValuationType
Maybe NormalSign
BalanceCalculation
BalanceAccumulation
AccountListMode
CommodityLayout
Costing
StringFormat
Period
Interval
commodity_layout_ :: CommodityLayout
transpose_ :: Bool
color_ :: Bool
normalbalance_ :: Maybe NormalSign
invert_ :: Bool
percent_ :: Bool
sort_amount_ :: Bool
show_costs_ :: Bool
no_total_ :: Bool
row_total_ :: Bool
declared_ :: Bool
drop_ :: Int
accountlistmode_ :: AccountListMode
budgetpat_ :: Maybe Text
balanceaccum_ :: BalanceAccumulation
balancecalc_ :: BalanceCalculation
txn_dates_ :: Bool
related_ :: Bool
average_ :: Bool
querystring_ :: [Text]
pretty_ :: Bool
format_ :: StringFormat
real_ :: Bool
no_elide_ :: Bool
empty_ :: Bool
date2_ :: Bool
depth_ :: Maybe Int
infer_prices_ :: Bool
value_ :: Maybe ValuationType
cost_ :: Costing
statuses_ :: [Status]
interval_ :: Interval
period_ :: Period
period_ :: ReportOpts -> Period
interval_ :: ReportOpts -> Interval
statuses_ :: ReportOpts -> [Status]
cost_ :: ReportOpts -> Costing
value_ :: ReportOpts -> Maybe ValuationType
infer_prices_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
date2_ :: ReportOpts -> Bool
empty_ :: ReportOpts -> Bool
no_elide_ :: ReportOpts -> Bool
real_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
average_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
balancecalc_ :: ReportOpts -> BalanceCalculation
balanceaccum_ :: ReportOpts -> BalanceAccumulation
budgetpat_ :: ReportOpts -> Maybe Text
accountlistmode_ :: ReportOpts -> AccountListMode
drop_ :: ReportOpts -> Int
declared_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
percent_ :: ReportOpts -> Bool
invert_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
color_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
commodity_layout_ :: ReportOpts -> CommodityLayout
..} = AmountDisplayOpts
oneLine {displayColour :: Bool
displayColour = Bool
isTable Bool -> Bool -> Bool
&& Bool
color_}
tests_Balance :: TestTree
tests_Balance = CommandDoc -> [TestTree] -> TestTree
testGroup CommandDoc
"Balance" [
CommandDoc -> [TestTree] -> TestTree
testGroup CommandDoc
"balanceReportAsText" [
CommandDoc -> IO () -> TestTree
testCase 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{_rsReportOpts :: ReportOpts
_rsReportOpts=ReportOpts
defreportopts{no_total_ :: Bool
no_total_=Bool
True}}
Builder -> Text
TB.toLazyText (ReportOpts -> BalanceReport -> Builder
balanceReportAsText (ReportSpec -> ReportOpts
_rsReportOpts ReportSpec
rspec) (ReportSpec -> Journal -> BalanceReport
balanceReport ReportSpec
rspec{_rsDay :: Day
_rsDay=Integer -> Int -> Int -> Day
fromGregorian Integer
2008 Int
11 Int
26} Journal
j))
Text -> Text -> IO ()
forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
@?=
[Text] -> Text
TL.unlines
[Text
" -100 актив:наличные"
,Text
" 100 расходы:покупки"
]
]
]