{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ExtendedDefaultRules #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
module Hledger.Cli.Commands.Balance (
balancemode
,balance
,balanceReportAsText
,balanceReportAsCsv
,balanceReportAsSpreadsheet
,balanceReportItemAsText
,multiBalanceRowAsCsvText
,multiBalanceRowAsText
,multiBalanceReportAsText
,multiBalanceReportAsCsv
,multiBalanceReportAsHtml
,multiBalanceReportHtmlRows
,multiBalanceReportHtmlFootRow
,multiBalanceReportAsTable
,multiBalanceReportTableAsText
,multiBalanceReportAsSpreadsheet
,stylesheet_
,styles_
,bold
,doubleborder
,topdoubleborder
,bottomdoubleborder
,alignright
,alignleft
,aligncenter
,collapse
,lpad
,rpad
,hpad
,vpad
,tests_Balance
) where
import Control.Arrow ((***))
import Data.Decimal (roundTo)
import Data.Default (def)
import Data.Function (on)
import Data.List (find, transpose, foldl')
import qualified Data.Map as Map
import qualified Data.Set as S
import Data.Maybe (catMaybes, fromMaybe)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Builder as TB
import Data.Time (addDays, fromGregorian)
import System.Console.CmdArgs.Explicit as C (flagNone, flagReq, flagOpt)
import Lucid as L hiding (value_)
import Safe (headMay, maximumMay)
import Text.Tabular.AsciiWide
(Header(..), Align(..), Properties(..), Cell(..), Table(..), TableOpts(..),
cellWidth, concatTables, renderColumns, renderRowB, renderTableByRowsB, textCell)
import qualified System.IO as IO
import Hledger
import Hledger.Cli.CliOptions
import Hledger.Cli.Utils
import Hledger.Write.Csv (CSV, printCSV, printTSV)
import Hledger.Write.Ods (printFods)
import Hledger.Write.Html (printHtml)
import qualified Hledger.Write.Spreadsheet as Ods
balancemode :: Mode RawOpts
balancemode = CommandHelpStr
-> [Flag RawOpts]
-> [(CommandHelpStr, [Flag RawOpts])]
-> [Flag RawOpts]
-> ([Arg RawOpts], Maybe (Arg RawOpts))
-> Mode RawOpts
hledgerCommandMode
$(embedFileRelative "Hledger/Cli/Commands/Balance.txt")
(
[[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"sum"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"sum")
CommandHelpStr
"show sum of posting amounts (default)"
,CommandHelpStr
-> [CommandHelpStr]
-> Update RawOpts
-> CommandHelpStr
-> CommandHelpStr
-> Flag RawOpts
forall a.
CommandHelpStr
-> [CommandHelpStr]
-> Update a
-> CommandHelpStr
-> CommandHelpStr
-> Flag a
flagOpt CommandHelpStr
"" [CommandHelpStr
"budget"] (\CommandHelpStr
s RawOpts
opts -> RawOpts -> Either CommandHelpStr RawOpts
forall a b. b -> Either a b
Right (RawOpts -> Either CommandHelpStr RawOpts)
-> RawOpts -> Either CommandHelpStr RawOpts
forall a b. (a -> b) -> a -> b
$ CommandHelpStr -> CommandHelpStr -> RawOpts -> RawOpts
setopt CommandHelpStr
"budget" CommandHelpStr
s RawOpts
opts) CommandHelpStr
"DESCPAT"
([CommandHelpStr] -> CommandHelpStr
unlines
[ CommandHelpStr
"show sum of posting amounts together with budget goals defined by periodic"
, CommandHelpStr
"transactions. With a DESCPAT argument (must be separated by = not space),"
, CommandHelpStr
"use only periodic transactions with matching description"
, CommandHelpStr
"(case insensitive substring match)."
])
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"valuechange"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"valuechange")
CommandHelpStr
"show total change of value of period-end historical balances (caused by deposits, withdrawals, market price fluctuations)"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"gain"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"gain")
CommandHelpStr
"show unrealised capital gain/loss (historical balance value minus cost basis)"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"count"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"count") CommandHelpStr
"show the count of postings"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"change"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"change")
CommandHelpStr
"accumulate amounts from column start to column end (in multicolumn reports, default)"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"cumulative"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"cumulative")
CommandHelpStr
"accumulate amounts from report start (specified by e.g. -b/--begin) to column end"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"historical",CommandHelpStr
"H"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"historical")
CommandHelpStr
"accumulate amounts from journal start to column end (includes postings before report start date)"
]
[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]
++
[[CommandHelpStr]
-> Update RawOpts
-> CommandHelpStr
-> CommandHelpStr
-> Flag RawOpts
forall a.
[CommandHelpStr]
-> Update a -> CommandHelpStr -> CommandHelpStr -> Flag a
flagReq [CommandHelpStr
"drop"] (\CommandHelpStr
s RawOpts
opts -> RawOpts -> Either CommandHelpStr RawOpts
forall a b. b -> Either a b
Right (RawOpts -> Either CommandHelpStr RawOpts)
-> RawOpts -> Either CommandHelpStr RawOpts
forall a b. (a -> b) -> a -> b
$ CommandHelpStr -> CommandHelpStr -> RawOpts -> RawOpts
setopt CommandHelpStr
"drop" CommandHelpStr
s RawOpts
opts) CommandHelpStr
"N" CommandHelpStr
"omit N leading account name parts (in flat mode)"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"declared"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"declared") CommandHelpStr
"include non-parent declared accounts (best used with -E)"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"average",CommandHelpStr
"A"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"average") CommandHelpStr
"show a row average column (in multicolumn reports)"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"related",CommandHelpStr
"r"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"related") CommandHelpStr
"show postings' siblings instead"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"row-total",CommandHelpStr
"T"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"row-total") CommandHelpStr
"show a row total column (in multicolumn reports)"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"summary-only"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"summary-only") CommandHelpStr
"display only row summaries (e.g. row total, average) (in multicolumn reports)"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"no-total",CommandHelpStr
"N"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"no-total") CommandHelpStr
"omit the final total row"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"no-elide"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"no-elide") CommandHelpStr
"don't squash boring parent accounts (in tree mode)"
,[CommandHelpStr]
-> Update RawOpts
-> CommandHelpStr
-> CommandHelpStr
-> Flag RawOpts
forall a.
[CommandHelpStr]
-> Update a -> CommandHelpStr -> CommandHelpStr -> Flag a
flagReq [CommandHelpStr
"format"] (\CommandHelpStr
s RawOpts
opts -> RawOpts -> Either CommandHelpStr RawOpts
forall a b. b -> Either a b
Right (RawOpts -> Either CommandHelpStr RawOpts)
-> RawOpts -> Either CommandHelpStr RawOpts
forall a b. (a -> b) -> a -> b
$ CommandHelpStr -> CommandHelpStr -> RawOpts -> RawOpts
setopt CommandHelpStr
"format" CommandHelpStr
s RawOpts
opts) CommandHelpStr
"FORMATSTR" CommandHelpStr
"use this custom line format (in simple reports)"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"sort-amount",CommandHelpStr
"S"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"sort-amount") CommandHelpStr
"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."
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"percent", CommandHelpStr
"%"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"percent") CommandHelpStr
"express values in percentage of each column's total"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"invert"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"invert") CommandHelpStr
"display all amounts with reversed sign"
,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"transpose"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"transpose") CommandHelpStr
"transpose rows and columns"
,[CommandHelpStr]
-> Update RawOpts
-> CommandHelpStr
-> CommandHelpStr
-> Flag RawOpts
forall a.
[CommandHelpStr]
-> Update a -> CommandHelpStr -> CommandHelpStr -> Flag a
flagReq [CommandHelpStr
"layout"] (\CommandHelpStr
s RawOpts
opts -> RawOpts -> Either CommandHelpStr RawOpts
forall a b. b -> Either a b
Right (RawOpts -> Either CommandHelpStr RawOpts)
-> RawOpts -> Either CommandHelpStr RawOpts
forall a b. (a -> b) -> a -> b
$ CommandHelpStr -> CommandHelpStr -> RawOpts -> RawOpts
setopt CommandHelpStr
"layout" CommandHelpStr
s RawOpts
opts) CommandHelpStr
"ARG"
([CommandHelpStr] -> CommandHelpStr
unlines
[CommandHelpStr
"how to lay out multi-commodity amounts and the overall table:"
,CommandHelpStr
"'wide[,WIDTH]': commodities on one line"
,CommandHelpStr
"'tall' : commodities on separate lines"
,CommandHelpStr
"'bare' : commodity symbols in one column"
,CommandHelpStr
"'tidy' : every attribute in its own column"
])
,[CommandHelpStr] -> Flag RawOpts
outputFormatFlag [CommandHelpStr
"txt",CommandHelpStr
"html",CommandHelpStr
"csv",CommandHelpStr
"tsv",CommandHelpStr
"json",CommandHelpStr
"fods"]
,Flag RawOpts
outputFileFlag
]
)
[(CommandHelpStr, [Flag RawOpts])]
cligeneralflagsgroups1
([Flag RawOpts]
hiddenflags [Flag RawOpts] -> [Flag RawOpts] -> [Flag RawOpts]
forall a. [a] -> [a] -> [a]
++
[ [CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"commodity-column"] (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"commodity-column")
CommandHelpStr
"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
$ CommandHelpStr -> Arg RawOpts
argsFlag CommandHelpStr
"[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 rspan :: DateSpan
rspan = (DateSpan, [DateSpan]) -> DateSpan
forall a b. (a, b) -> a
fst ((DateSpan, [DateSpan]) -> DateSpan)
-> (DateSpan, [DateSpan]) -> DateSpan
forall a b. (a -> b) -> a -> b
$ Journal -> ReportSpec -> (DateSpan, [DateSpan])
reportSpan Journal
j ReportSpec
rspec
budgetreport :: BudgetReport
budgetreport = Map Text AmountStyle -> BudgetReport -> BudgetReport
forall a. HasAmounts a => Map Text AmountStyle -> a -> a
styleAmounts Map Text AmountStyle
styles (BudgetReport -> BudgetReport) -> BudgetReport -> BudgetReport
forall a b. (a -> b) -> a -> b
$ 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
rspan Journal
j
render :: BudgetReport -> Text
render = case CommandHelpStr
fmt of
CommandHelpStr
"txt" -> ReportOpts -> BudgetReport -> Text
budgetReportAsText ReportOpts
ropts
CommandHelpStr
"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
CommandHelpStr
"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
CommandHelpStr
"tsv" -> CSV -> Text
printTSV (CSV -> Text) -> (BudgetReport -> CSV) -> BudgetReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> BudgetReport -> CSV
budgetReportAsCsv ReportOpts
ropts
CommandHelpStr
"html" -> (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
. Html () -> Text
forall a. Html a -> Text
L.renderText (Html () -> Text)
-> (BudgetReport -> Html ()) -> BudgetReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
[[Cell (Html ())]] -> Html ()
printHtml ([[Cell (Html ())]] -> Html ())
-> (BudgetReport -> [[Cell (Html ())]]) -> BudgetReport -> Html ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Cell Text] -> [Cell (Html ())])
-> [[Cell Text]] -> [[Cell (Html ())]]
forall a b. (a -> b) -> [a] -> [b]
map ((Cell Text -> Cell (Html ())) -> [Cell Text] -> [Cell (Html ())]
forall a b. (a -> b) -> [a] -> [b]
map ((Text -> Html ()) -> Cell Text -> Cell (Html ())
forall a b. (a -> b) -> Cell a -> Cell b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> HtmlT m ()
L.toHtml)) ([[Cell Text]] -> [[Cell (Html ())]])
-> (BudgetReport -> [[Cell Text]])
-> BudgetReport
-> [[Cell (Html ())]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> BudgetReport -> [[Cell Text]]
budgetReportAsSpreadsheet ReportOpts
ropts
CommandHelpStr
"fods" -> TextEncoding
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]]) -> Text
printFods TextEncoding
IO.localeEncoding (Map Text ((Maybe Int, Maybe Int), [[Cell Text]]) -> Text)
-> (BudgetReport
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]]))
-> BudgetReport
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
Text
-> ((Maybe Int, Maybe Int), [[Cell Text]])
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]])
forall k a. k -> a -> Map k a
Map.singleton Text
"Hledger" (((Maybe Int, Maybe Int), [[Cell Text]])
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]]))
-> (BudgetReport -> ((Maybe Int, Maybe Int), [[Cell Text]]))
-> BudgetReport
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,) (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1, Maybe Int
forall a. Maybe a
Nothing) ([[Cell Text]] -> ((Maybe Int, Maybe Int), [[Cell Text]]))
-> (BudgetReport -> [[Cell Text]])
-> BudgetReport
-> ((Maybe Int, Maybe Int), [[Cell Text]])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> BudgetReport -> [[Cell Text]]
budgetReportAsSpreadsheet ReportOpts
ropts
CommandHelpStr
_ -> CommandHelpStr -> BudgetReport -> Text
forall a. CommandHelpStr -> a
error' (CommandHelpStr -> BudgetReport -> Text)
-> CommandHelpStr -> BudgetReport -> Text
forall a b. (a -> b) -> a -> b
$ CommandHelpStr -> CommandHelpStr
unsupportedOutputFormatError CommandHelpStr
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 = Map Text AmountStyle -> MultiBalanceReport -> MultiBalanceReport
forall a. HasAmounts a => Map Text AmountStyle -> a -> a
styleAmounts Map Text AmountStyle
styles (MultiBalanceReport -> MultiBalanceReport)
-> MultiBalanceReport -> MultiBalanceReport
forall a b. (a -> b) -> a -> b
$ ReportSpec -> Journal -> MultiBalanceReport
multiBalanceReport ReportSpec
rspec Journal
j
render :: MultiBalanceReport -> Text
render = case CommandHelpStr
fmt of
CommandHelpStr
"txt" -> ReportOpts -> MultiBalanceReport -> Text
multiBalanceReportAsText ReportOpts
ropts
CommandHelpStr
"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
CommandHelpStr
"tsv" -> CSV -> Text
printTSV (CSV -> Text)
-> (MultiBalanceReport -> CSV) -> MultiBalanceReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> MultiBalanceReport -> CSV
multiBalanceReportAsCsv ReportOpts
ropts
CommandHelpStr
"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
CommandHelpStr
"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
CommandHelpStr
"fods" -> TextEncoding
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]]) -> Text
printFods TextEncoding
IO.localeEncoding (Map Text ((Maybe Int, Maybe Int), [[Cell Text]]) -> Text)
-> (MultiBalanceReport
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]]))
-> MultiBalanceReport
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
Text
-> ((Maybe Int, Maybe Int), [[Cell Text]])
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]])
forall k a. k -> a -> Map k a
Map.singleton Text
"Hledger" (((Maybe Int, Maybe Int), [[Cell Text]])
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]]))
-> (MultiBalanceReport -> ((Maybe Int, Maybe Int), [[Cell Text]]))
-> MultiBalanceReport
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts
-> MultiBalanceReport -> ((Maybe Int, Maybe Int), [[Cell Text]])
multiBalanceReportAsSpreadsheet ReportOpts
ropts
CommandHelpStr
_ -> Text -> MultiBalanceReport -> Text
forall a b. a -> b -> a
const (Text -> MultiBalanceReport -> Text)
-> Text -> MultiBalanceReport -> Text
forall a b. (a -> b) -> a -> b
$ CommandHelpStr -> Text
forall a. CommandHelpStr -> a
error' (CommandHelpStr -> Text) -> CommandHelpStr -> Text
forall a b. (a -> b) -> a -> b
$ CommandHelpStr -> CommandHelpStr
unsupportedOutputFormatError CommandHelpStr
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 = Map Text AmountStyle -> BalanceReport -> BalanceReport
forall a. HasAmounts a => Map Text AmountStyle -> a -> a
styleAmounts Map Text AmountStyle
styles (BalanceReport -> BalanceReport) -> BalanceReport -> BalanceReport
forall a b. (a -> b) -> a -> b
$ ReportSpec -> Journal -> BalanceReport
balanceReport ReportSpec
rspec Journal
j
render :: ReportOpts -> BalanceReport -> Text
render = case CommandHelpStr
fmt of
CommandHelpStr
"txt" -> \ReportOpts
ropts1 -> 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
ropts1
CommandHelpStr
"csv" -> \ReportOpts
ropts1 -> CSV -> Text
printCSV (CSV -> Text) -> (BalanceReport -> CSV) -> BalanceReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> BalanceReport -> CSV
balanceReportAsCsv ReportOpts
ropts1
CommandHelpStr
"tsv" -> \ReportOpts
ropts1 -> CSV -> Text
printTSV (CSV -> Text) -> (BalanceReport -> CSV) -> BalanceReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> BalanceReport -> CSV
balanceReportAsCsv ReportOpts
ropts1
CommandHelpStr
"html" -> \ReportOpts
ropts1 -> (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
. Html () -> Text
forall a. Html a -> Text
L.renderText (Html () -> Text)
-> (BalanceReport -> Html ()) -> BalanceReport -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
[[Cell (Html ())]] -> Html ()
printHtml ([[Cell (Html ())]] -> Html ())
-> (BalanceReport -> [[Cell (Html ())]])
-> BalanceReport
-> Html ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Cell Text] -> [Cell (Html ())])
-> [[Cell Text]] -> [[Cell (Html ())]]
forall a b. (a -> b) -> [a] -> [b]
map ((Cell Text -> Cell (Html ())) -> [Cell Text] -> [Cell (Html ())]
forall a b. (a -> b) -> [a] -> [b]
map ((Text -> Html ()) -> Cell Text -> Cell (Html ())
forall a b. (a -> b) -> Cell a -> Cell b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> HtmlT m ()
L.toHtml)) ([[Cell Text]] -> [[Cell (Html ())]])
-> (BalanceReport -> [[Cell Text]])
-> BalanceReport
-> [[Cell (Html ())]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> BalanceReport -> [[Cell Text]]
balanceReportAsSpreadsheet ReportOpts
ropts1
CommandHelpStr
"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
CommandHelpStr
"fods" -> \ReportOpts
ropts1 -> TextEncoding
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]]) -> Text
printFods TextEncoding
IO.localeEncoding (Map Text ((Maybe Int, Maybe Int), [[Cell Text]]) -> Text)
-> (BalanceReport
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]]))
-> BalanceReport
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text
-> ((Maybe Int, Maybe Int), [[Cell Text]])
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]])
forall k a. k -> a -> Map k a
Map.singleton Text
"Hledger" (((Maybe Int, Maybe Int), [[Cell Text]])
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]]))
-> (BalanceReport -> ((Maybe Int, Maybe Int), [[Cell Text]]))
-> BalanceReport
-> Map Text ((Maybe Int, Maybe Int), [[Cell Text]])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,) (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1, Maybe Int
forall a. Maybe a
Nothing) ([[Cell Text]] -> ((Maybe Int, Maybe Int), [[Cell Text]]))
-> (BalanceReport -> [[Cell Text]])
-> BalanceReport
-> ((Maybe Int, Maybe Int), [[Cell Text]])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> BalanceReport -> [[Cell Text]]
balanceReportAsSpreadsheet ReportOpts
ropts1
CommandHelpStr
_ -> CommandHelpStr -> ReportOpts -> BalanceReport -> Text
forall a. CommandHelpStr -> a
error' (CommandHelpStr -> ReportOpts -> BalanceReport -> Text)
-> CommandHelpStr -> ReportOpts -> BalanceReport -> Text
forall a b. (a -> b) -> a -> b
$ CommandHelpStr -> CommandHelpStr
unsupportedOutputFormatError CommandHelpStr
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
styles :: Map Text AmountStyle
styles = Rounding -> Journal -> Map Text AmountStyle
journalCommodityStylesWith Rounding
HardRounding Journal
j
ropts :: ReportOpts
ropts@ReportOpts{Bool
Int
[Text]
[Status]
SortSpec
Maybe Int
Maybe Text
Maybe NormalSign
Maybe ConversionOp
Maybe ValuationType
StringFormat
Interval
Period
AccountListMode
BalanceAccumulation
BalanceCalculation
Layout
balancecalc_ :: BalanceCalculation
period_ :: Period
interval_ :: Interval
statuses_ :: [Status]
conversionop_ :: Maybe ConversionOp
value_ :: Maybe ValuationType
infer_prices_ :: Bool
depth_ :: Maybe Int
date2_ :: Bool
empty_ :: Bool
no_elide_ :: Bool
real_ :: Bool
format_ :: StringFormat
pretty_ :: Bool
querystring_ :: [Text]
average_ :: Bool
related_ :: Bool
sortspec_ :: SortSpec
txn_dates_ :: Bool
balanceaccum_ :: BalanceAccumulation
budgetpat_ :: Maybe Text
accountlistmode_ :: AccountListMode
drop_ :: Int
declared_ :: Bool
row_total_ :: Bool
no_total_ :: Bool
summary_only_ :: Bool
show_costs_ :: Bool
sort_amount_ :: Bool
percent_ :: Bool
invert_ :: Bool
normalbalance_ :: Maybe NormalSign
color_ :: Bool
transpose_ :: Bool
layout_ :: Layout
accountlistmode_ :: ReportOpts -> AccountListMode
average_ :: ReportOpts -> Bool
balanceaccum_ :: ReportOpts -> BalanceAccumulation
balancecalc_ :: ReportOpts -> BalanceCalculation
budgetpat_ :: ReportOpts -> Maybe Text
color_ :: ReportOpts -> Bool
conversionop_ :: ReportOpts -> Maybe ConversionOp
date2_ :: ReportOpts -> Bool
declared_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
drop_ :: ReportOpts -> Int
empty_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
infer_prices_ :: ReportOpts -> Bool
interval_ :: ReportOpts -> Interval
invert_ :: ReportOpts -> Bool
layout_ :: ReportOpts -> Layout
no_elide_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
percent_ :: ReportOpts -> Bool
period_ :: ReportOpts -> Period
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
real_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
sortspec_ :: ReportOpts -> SortSpec
statuses_ :: ReportOpts -> [Status]
summary_only_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
value_ :: ReportOpts -> Maybe ValuationType
..} = ReportSpec -> ReportOpts
_rsReportOpts ReportSpec
rspec
multiperiod :: Bool
multiperiod = Interval
interval_ Interval -> Interval -> Bool
forall a. Eq a => a -> a -> Bool
/= Interval
NoInterval Bool -> Bool -> Bool
|| (Layout
layout_ Layout -> Layout -> Bool
forall a. Eq a => a -> a -> Bool
== Layout
LayoutTidy Bool -> Bool -> Bool
&& Bool
delimited)
delimited :: Bool
delimited = CommandHelpStr
fmt CommandHelpStr -> CommandHelpStr -> Bool
forall a. Eq a => a -> a -> Bool
== CommandHelpStr
"csv" Bool -> Bool -> Bool
|| CommandHelpStr
fmt CommandHelpStr -> CommandHelpStr -> Bool
forall a. Eq a => a -> a -> Bool
== CommandHelpStr
"tsv"
fmt :: CommandHelpStr
fmt = CliOpts -> CommandHelpStr
outputFormatFromOpts CliOpts
opts
totalRowHeadingText :: Text
totalRowHeadingText = Text
""
totalRowHeadingBudgetText :: Text
totalRowHeadingBudgetText = Text
""
totalRowHeadingHtml :: Text
totalRowHeadingHtml = Text
"Total:"
totalRowHeadingCsv :: Text
totalRowHeadingCsv = Text
"Total:"
totalRowHeadingBudgetCsv :: Text
totalRowHeadingBudgetCsv = Text
"Total:"
balanceReportAsCsv :: ReportOpts -> BalanceReport -> CSV
balanceReportAsCsv :: ReportOpts -> BalanceReport -> CSV
balanceReportAsCsv ReportOpts
opts =
([Cell Text] -> [Text]) -> [[Cell Text]] -> CSV
forall a b. (a -> b) -> [a] -> [b]
map ((Cell Text -> Text) -> [Cell Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Cell Text -> Text
forall text. Cell text -> text
Ods.cellContent) ([[Cell Text]] -> CSV)
-> (BalanceReport -> [[Cell Text]]) -> BalanceReport -> CSV
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReportOpts -> BalanceReport -> [[Cell Text]]
balanceReportAsSpreadsheet ReportOpts
opts
balanceReportAsText :: ReportOpts -> BalanceReport -> TB.Builder
balanceReportAsText :: ReportOpts -> BalanceReport -> Builder
balanceReportAsText ReportOpts
opts (([BalanceReportItem]
items, Change
total)) = case ReportOpts -> Layout
layout_ ReportOpts
opts of
Layout
LayoutBare | Bool
iscustom -> CommandHelpStr -> Builder
forall a. CommandHelpStr -> a
error' CommandHelpStr
"Custom format not supported with commodity columns"
Layout
LayoutBare -> ReportOpts -> BalanceReport -> Builder
bareLayoutBalanceReportAsText ReportOpts
opts (([BalanceReportItem]
items, Change
total))
Layout
_ -> [Builder] -> Builder
unlinesB [Builder]
ls 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]
ls, [[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, Change) -> (Builder, [Int])
renderBalanceReportItem ReportOpts
opts (Text
"",Int
0,Change
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 a. Num a => [a] -> a
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
"-"
bareLayoutBalanceReportAsText :: ReportOpts -> BalanceReport -> TB.Builder
bareLayoutBalanceReportAsText :: ReportOpts -> BalanceReport -> Builder
bareLayoutBalanceReportAsText ReportOpts
opts (([BalanceReportItem]
items, Change
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 a b. (a -> b) -> [a] -> [b]
map
(TableOpts -> [Int] -> Header Cell -> Builder
renderColumns TableOpts
forall a. Default a => a
def{tableBorders=singleColumnTableOuterBorder} [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
Group Properties
singleColumnTableInterColumnBorder ([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 a b. (a -> b) -> [a] -> [b]
map Cell -> Header Cell
forall h. h -> Header h
Header) ([[Cell]] -> Builder) -> [[Cell]] -> Builder
forall a b. (a -> b) -> a -> b
$
[[Cell]]
ls [[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, Change) -> [Cell]
render (a
_, Text
acctname, Int
dep, Change
amt) =
[ Align -> [WideBuilder] -> Cell
Cell Align
TopRight [WideBuilder]
damts
, Align -> [WideBuilder] -> Cell
Cell Align
TopLeft ((Text -> WideBuilder) -> [Text] -> [WideBuilder]
forall a b. (a -> b) -> [a] -> [b]
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 a. [a] -> 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 :: AmountFormat
dopts = AmountFormat
oneLineNoCostFmt{displayCommodity=layout_ opts /= LayoutBare, displayCommodityOrder=Just cs, displayColour=color_ opts}
cs :: [Text]
cs = if Change -> Bool
mixedAmountLooksZero Change
amt then [Text
""] else Set Text -> [Text]
forall a. Set a -> [a]
S.toList (Set Text -> [Text]) -> Set Text -> [Text]
forall a b. (a -> b) -> a -> b
$ Change -> Set Text
maCommodities Change
amt
dispname :: Text
dispname = Int -> Text -> Text
T.replicate ((Int
dep 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 = AmountFormat -> Change -> [WideBuilder]
showMixedAmountLinesB AmountFormat
dopts Change
amt
ls :: [[Cell]]
ls = (BalanceReportItem -> [Cell]) -> [BalanceReportItem] -> [[Cell]]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap BalanceReportItem -> [Cell]
forall {a}. (a, Text, Int, Change) -> [Cell]
render [BalanceReportItem]
items
totalline :: [Cell]
totalline = (CommandHelpStr, Text, Int, Change) -> [Cell]
forall {a}. (a, Text, Int, Change) -> [Cell]
render (CommandHelpStr
"", Text
"", Int
0, Change
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]]
ls)
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 a. a -> [a]
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
singleColumnTableOuterBorder :: Bool
singleColumnTableOuterBorder = ReportOpts -> Bool
pretty_ ReportOpts
opts
singleColumnTableInterColumnBorder :: Properties
singleColumnTableInterColumnBorder = if ReportOpts -> Bool
pretty_ ReportOpts
opts then Properties
SingleLine else Properties
NoLine
balanceReportItemAsText :: ReportOpts -> BalanceReportItem -> (TB.Builder, [Int])
balanceReportItemAsText :: ReportOpts -> BalanceReportItem -> (Builder, [Int])
balanceReportItemAsText ReportOpts
opts (Text
_, Text
accountName, Int
dep, Change
amt) =
ReportOpts -> (Text, Int, Change) -> (Builder, [Int])
renderBalanceReportItem ReportOpts
opts (Text
accountName, Int
dep, Change
amt)
renderBalanceReportItem :: ReportOpts -> (AccountName, Int, MixedAmount) -> (TB.Builder, [Int])
renderBalanceReportItem :: ReportOpts -> (Text, Int, Change) -> (Builder, [Int])
renderBalanceReportItem ReportOpts
opts (Text
acctname, Int
dep, Change
total) =
case ReportOpts -> StringFormat
format_ ReportOpts
opts of
OneLine [StringFormatComponent]
comps -> [Cell] -> (Builder, [Int])
renderRowFromComponents ([Cell] -> (Builder, [Int])) -> [Cell] -> (Builder, [Int])
forall a b. (a -> b) -> a -> b
$ Bool -> Bool -> [StringFormatComponent] -> [Cell]
renderComponents Bool
True Bool
True [StringFormatComponent]
comps
TopAligned [StringFormatComponent]
comps -> [Cell] -> (Builder, [Int])
renderRowFromComponents ([Cell] -> (Builder, [Int])) -> [Cell] -> (Builder, [Int])
forall a b. (a -> b) -> a -> b
$ Bool -> Bool -> [StringFormatComponent] -> [Cell]
renderComponents Bool
True Bool
False [StringFormatComponent]
comps
BottomAligned [StringFormatComponent]
comps -> [Cell] -> (Builder, [Int])
renderRowFromComponents ([Cell] -> (Builder, [Int])) -> [Cell] -> (Builder, [Int])
forall a b. (a -> b) -> a -> b
$ Bool -> Bool -> [StringFormatComponent] -> [Cell]
renderComponents Bool
False Bool
False [StringFormatComponent]
comps
where
renderRowFromComponents :: [Cell] -> (TB.Builder, [Int])
renderRowFromComponents :: [Cell] -> (Builder, [Int])
renderRowFromComponents [Cell]
cs =
( TableOpts -> Header Cell -> Builder
renderRowB TableOpts
forall a. Default a => a
def{tableBorders=False, borderSpaces=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
Group Properties
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
Header [Cell]
cs
, (Cell -> Int) -> [Cell] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Cell -> Int
cellWidth [Cell]
cs
)
renderComponents :: Bool -> Bool -> [StringFormatComponent] -> [Cell]
renderComponents :: Bool -> Bool -> [StringFormatComponent] -> [Cell]
renderComponents Bool
topaligned Bool
oneline = (StringFormatComponent -> Cell)
-> [StringFormatComponent] -> [Cell]
forall a b. (a -> b) -> [a] -> [b]
map (Bool
-> Bool
-> ReportOpts
-> (Text, Int, Change)
-> StringFormatComponent
-> Cell
renderComponent Bool
topaligned Bool
oneline ReportOpts
opts (Text
acctname, Int
dep, Change
total))
renderComponent :: Bool -> Bool -> ReportOpts -> (AccountName, Int, MixedAmount) -> StringFormatComponent -> Cell
renderComponent :: Bool
-> Bool
-> ReportOpts
-> (Text, Int, Change)
-> StringFormatComponent
-> Cell
renderComponent Bool
_ Bool
_ ReportOpts
_ (Text, Int, Change)
_ (FormatLiteral Text
s) = Align -> Text -> Cell
textCell Align
TopLeft Text
s
renderComponent Bool
topaligned Bool
oneline ReportOpts
opts (Text
acctname, Int
dep, Change
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
dep 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 a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (WideBuilder -> Cell) -> WideBuilder -> Cell
forall a b. (a -> b) -> a -> b
$ AmountFormat -> Change -> WideBuilder
showMixedAmountB AmountFormat
dopts Change
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 :: AmountFormat
dopts = AmountFormat
noCostFmt{displayCommodity = layout_ opts /= LayoutBare
,displayOneLine = oneline
,displayMinWidth = mmin
,displayMaxWidth = mmax
,displayColour = color_ opts
}
balanceReportAsSpreadsheet :: ReportOpts -> BalanceReport -> [[Ods.Cell Text]]
balanceReportAsSpreadsheet :: ReportOpts -> BalanceReport -> [[Cell Text]]
balanceReportAsSpreadsheet ReportOpts
opts ([BalanceReportItem]
items, Change
total) =
[Cell Text]
headers [Cell Text] -> [[Cell Text]] -> [[Cell Text]]
forall a. a -> [a] -> [a]
:
(BalanceReportItem -> [[Cell Text]])
-> [BalanceReportItem] -> [[Cell Text]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(Text
a, Text
_, Int
_, Change
b) -> Text -> Change -> [[Cell Text]]
rows Text
a Change
b) [BalanceReportItem]
items [[Cell Text]] -> [[Cell Text]] -> [[Cell Text]]
forall a. [a] -> [a] -> [a]
++
if ReportOpts -> Bool
no_total_ ReportOpts
opts then []
else ([Cell Text] -> [Cell Text]) -> [[Cell Text]] -> [[Cell Text]]
forall a b. (a -> b) -> [a] -> [b]
map ((Cell Text -> Cell Text) -> [Cell Text] -> [Cell Text]
forall a b. (a -> b) -> [a] -> [b]
map (\Cell Text
c -> Cell Text
c {Ods.cellStyle = Ods.Body Ods.Total})) ([[Cell Text]] -> [[Cell Text]]) -> [[Cell Text]] -> [[Cell Text]]
forall a b. (a -> b) -> a -> b
$
Text -> Change -> [[Cell Text]]
rows Text
totalRowHeadingCsv Change
total
where
cell :: text -> Cell text
cell = text -> Cell text
forall text. text -> Cell text
Ods.defaultCell
headers :: [Cell Text]
headers =
(Text -> Cell Text) -> [Text] -> [Cell Text]
forall a b. (a -> b) -> [a] -> [b]
map (\Text
content -> (Text -> Cell Text
forall text. text -> Cell text
cell Text
content) {Ods.cellStyle = Ods.Head}) ([Text] -> [Cell Text]) -> [Text] -> [Cell Text]
forall a b. (a -> b) -> a -> b
$
Text
"account" Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: case ReportOpts -> Layout
layout_ ReportOpts
opts of
Layout
LayoutBare -> [Text
"commodity", Text
"balance"]
Layout
_ -> [Text
"balance"]
rows :: AccountName -> MixedAmount -> [[Ods.Cell Text]]
rows :: Text -> Change -> [[Cell Text]]
rows Text
name Change
ma = case ReportOpts -> Layout
layout_ ReportOpts
opts of
Layout
LayoutBare ->
(Amount -> [Cell Text]) -> [Amount] -> [[Cell Text]]
forall a b. (a -> b) -> [a] -> [b]
map (\Amount
a ->
[Text -> Cell Text
showName Text
name,
Text -> Cell Text
forall text. text -> Cell text
cell (Text -> Cell Text) -> Text -> Cell Text
forall a b. (a -> b) -> a -> b
$ Amount -> Text
acommodity Amount
a,
Change -> Cell Text
renderAmount (Change -> Cell Text) -> Change -> Cell Text
forall a b. (a -> b) -> a -> b
$ Amount -> Change
mixedAmount Amount
a])
([Amount] -> [[Cell Text]])
-> (Change -> [Amount]) -> Change -> [[Cell Text]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Change -> [Amount]
amounts (Change -> [[Cell Text]]) -> Change -> [[Cell Text]]
forall a b. (a -> b) -> a -> b
$ Change -> Change
mixedAmountStripCosts Change
ma
Layout
_ -> [[Text -> Cell Text
showName Text
name, Change -> Cell Text
renderAmount Change
ma]]
showName :: Text -> Cell Text
showName = Text -> Cell Text
forall text. text -> Cell text
cell (Text -> Cell Text) -> (Text -> Text) -> Text -> Cell Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text -> Text
accountNameDrop (ReportOpts -> Int
drop_ ReportOpts
opts)
renderAmount :: Change -> Cell Text
renderAmount Change
mixedAmt = WideBuilder -> Text
wbToText (WideBuilder -> Text) -> Cell WideBuilder -> Cell Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> AmountFormat -> Change -> Cell WideBuilder
cellFromMixedAmount AmountFormat
bopts Change
mixedAmt
where
bopts :: AmountFormat
bopts = AmountFormat
machineFmt{displayCommodity=showcomm, displayCommodityOrder = commorder}
(Bool
showcomm, Maybe [Text]
commorder)
| ReportOpts -> Layout
layout_ ReportOpts
opts Layout -> Layout -> Bool
forall a. Eq a => a -> a -> Bool
== Layout
LayoutBare = (Bool
False, [Text] -> Maybe [Text]
forall a. a -> Maybe a
Just ([Text] -> Maybe [Text]) -> [Text] -> Maybe [Text]
forall a b. (a -> b) -> a -> b
$ Set Text -> [Text]
forall a. Set a -> [a]
S.toList (Set Text -> [Text]) -> Set Text -> [Text]
forall a b. (a -> b) -> a -> b
$ Change -> Set Text
maCommodities Change
mixedAmt)
| Bool
otherwise = (Bool
True, Maybe [Text]
forall a. Maybe a
Nothing)
cellFromMixedAmount :: AmountFormat -> MixedAmount -> Ods.Cell WideBuilder
cellFromMixedAmount :: AmountFormat -> Change -> Cell WideBuilder
cellFromMixedAmount AmountFormat
bopts Change
mixedAmt =
(WideBuilder -> Cell WideBuilder
forall text. text -> Cell text
Ods.defaultCell (WideBuilder -> Cell WideBuilder)
-> WideBuilder -> Cell WideBuilder
forall a b. (a -> b) -> a -> b
$ AmountFormat -> Change -> WideBuilder
showMixedAmountB AmountFormat
bopts Change
mixedAmt) {
Ods.cellType =
case unifyMixedAmount mixedAmt of
Just Amount
amt -> AmountFormat -> Amount -> Type
amountType AmountFormat
bopts Amount
amt
Maybe Amount
Nothing -> Type
Ods.TypeMixedAmount
}
cellsFromMixedAmount :: AmountFormat -> MixedAmount -> [Ods.Cell WideBuilder]
cellsFromMixedAmount :: AmountFormat -> Change -> [Cell WideBuilder]
cellsFromMixedAmount AmountFormat
bopts Change
mixedAmt =
((WideBuilder, Amount) -> Cell WideBuilder)
-> [(WideBuilder, Amount)] -> [Cell WideBuilder]
forall a b. (a -> b) -> [a] -> [b]
map
(\(WideBuilder
str,Amount
amt) ->
(WideBuilder -> Cell WideBuilder
forall text. text -> Cell text
Ods.defaultCell WideBuilder
str) {Ods.cellType = amountType bopts amt})
(AmountFormat -> Change -> [(WideBuilder, Amount)]
showMixedAmountLinesPartsB AmountFormat
bopts Change
mixedAmt)
amountType :: AmountFormat -> Amount -> Ods.Type
amountType :: AmountFormat -> Amount -> Type
amountType AmountFormat
bopts Amount
amt =
Amount -> Type
Ods.TypeAmount (Amount -> Type) -> Amount -> Type
forall a b. (a -> b) -> a -> b
$
if AmountFormat -> Bool
displayCommodity AmountFormat
bopts
then Amount
amt
else Amount
amt {acommodity = T.empty}
multiBalanceReportAsCsv :: ReportOpts -> MultiBalanceReport -> CSV
multiBalanceReportAsCsv :: ReportOpts -> MultiBalanceReport -> CSV
multiBalanceReportAsCsv opts :: ReportOpts
opts@ReportOpts{Bool
Int
[Text]
[Status]
SortSpec
Maybe Int
Maybe Text
Maybe NormalSign
Maybe ConversionOp
Maybe ValuationType
StringFormat
Interval
Period
AccountListMode
BalanceAccumulation
BalanceCalculation
Layout
accountlistmode_ :: ReportOpts -> AccountListMode
average_ :: ReportOpts -> Bool
balanceaccum_ :: ReportOpts -> BalanceAccumulation
balancecalc_ :: ReportOpts -> BalanceCalculation
budgetpat_ :: ReportOpts -> Maybe Text
color_ :: ReportOpts -> Bool
conversionop_ :: ReportOpts -> Maybe ConversionOp
date2_ :: ReportOpts -> Bool
declared_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
drop_ :: ReportOpts -> Int
empty_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
infer_prices_ :: ReportOpts -> Bool
interval_ :: ReportOpts -> Interval
invert_ :: ReportOpts -> Bool
layout_ :: ReportOpts -> Layout
no_elide_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
percent_ :: ReportOpts -> Bool
period_ :: ReportOpts -> Period
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
real_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
sortspec_ :: ReportOpts -> SortSpec
statuses_ :: ReportOpts -> [Status]
summary_only_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
value_ :: ReportOpts -> Maybe ValuationType
period_ :: Period
interval_ :: Interval
statuses_ :: [Status]
conversionop_ :: Maybe ConversionOp
value_ :: Maybe ValuationType
infer_prices_ :: Bool
depth_ :: Maybe Int
date2_ :: Bool
empty_ :: Bool
no_elide_ :: Bool
real_ :: Bool
format_ :: StringFormat
pretty_ :: Bool
querystring_ :: [Text]
average_ :: Bool
related_ :: Bool
sortspec_ :: SortSpec
txn_dates_ :: Bool
balancecalc_ :: BalanceCalculation
balanceaccum_ :: BalanceAccumulation
budgetpat_ :: Maybe Text
accountlistmode_ :: AccountListMode
drop_ :: Int
declared_ :: Bool
row_total_ :: Bool
no_total_ :: Bool
summary_only_ :: Bool
show_costs_ :: Bool
sort_amount_ :: Bool
percent_ :: Bool
invert_ :: Bool
normalbalance_ :: Maybe NormalSign
color_ :: Bool
transpose_ :: Bool
layout_ :: Layout
..} MultiBalanceReport
report = CSV -> CSV
forall a. [[a]] -> [[a]]
maybeTranspose CSV
allRows
where
allRows :: CSV
allRows = case Layout
layout_ of
Layout
LayoutTidy -> CSV
rows
Layout
_ -> CSV
rows CSV -> CSV -> CSV
forall a. [a] -> [a] -> [a]
++ CSV
totals
(CSV
rows, CSV
totals) = Bool -> ReportOpts -> MultiBalanceReport -> (CSV, CSV)
multiBalanceReportAsCsvHelper Bool
False ReportOpts
opts MultiBalanceReport
report
maybeTranspose :: [[a]] -> [[a]]
maybeTranspose = if Bool
transpose_ then [[a]] -> [[a]]
forall a. [[a]] -> [[a]]
transpose else [[a]] -> [[a]]
forall a. a -> a
id
multiBalanceReportAsCsvHelper :: Bool -> ReportOpts -> MultiBalanceReport -> (CSV, CSV)
multiBalanceReportAsCsvHelper :: Bool -> ReportOpts -> MultiBalanceReport -> (CSV, CSV)
multiBalanceReportAsCsvHelper Bool
ishtml ReportOpts
opts =
(([Cell Text] -> [Text]) -> [[Cell Text]] -> CSV
forall a b. (a -> b) -> [a] -> [b]
map ((Cell Text -> Text) -> [Cell Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Cell Text -> Text
forall text. Cell text -> text
Ods.cellContent) ([[Cell Text]] -> CSV)
-> ([[Cell Text]] -> CSV)
-> ([[Cell Text]], [[Cell Text]])
-> (CSV, CSV)
forall b c b' c'. (b -> c) -> (b' -> c') -> (b, b') -> (c, c')
forall (a :: * -> * -> *) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
*** ([Cell Text] -> [Text]) -> [[Cell Text]] -> CSV
forall a b. (a -> b) -> [a] -> [b]
map ((Cell Text -> Text) -> [Cell Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Cell Text -> Text
forall text. Cell text -> text
Ods.cellContent)) (([[Cell Text]], [[Cell Text]]) -> (CSV, CSV))
-> (MultiBalanceReport -> ([[Cell Text]], [[Cell Text]]))
-> MultiBalanceReport
-> (CSV, CSV)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
Bool
-> ReportOpts
-> MultiBalanceReport
-> ([[Cell Text]], [[Cell Text]])
multiBalanceReportAsSpreadsheetHelper Bool
ishtml ReportOpts
opts
multiBalanceReportAsSpreadsheetHelper ::
Bool -> ReportOpts -> MultiBalanceReport -> ([[Ods.Cell Text]], [[Ods.Cell Text]])
multiBalanceReportAsSpreadsheetHelper :: Bool
-> ReportOpts
-> MultiBalanceReport
-> ([[Cell Text]], [[Cell Text]])
multiBalanceReportAsSpreadsheetHelper Bool
ishtml opts :: ReportOpts
opts@ReportOpts{Bool
Int
[Text]
[Status]
SortSpec
Maybe Int
Maybe Text
Maybe NormalSign
Maybe ConversionOp
Maybe ValuationType
StringFormat
Interval
Period
AccountListMode
BalanceAccumulation
BalanceCalculation
Layout
accountlistmode_ :: ReportOpts -> AccountListMode
average_ :: ReportOpts -> Bool
balanceaccum_ :: ReportOpts -> BalanceAccumulation
balancecalc_ :: ReportOpts -> BalanceCalculation
budgetpat_ :: ReportOpts -> Maybe Text
color_ :: ReportOpts -> Bool
conversionop_ :: ReportOpts -> Maybe ConversionOp
date2_ :: ReportOpts -> Bool
declared_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
drop_ :: ReportOpts -> Int
empty_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
infer_prices_ :: ReportOpts -> Bool
interval_ :: ReportOpts -> Interval
invert_ :: ReportOpts -> Bool
layout_ :: ReportOpts -> Layout
no_elide_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
percent_ :: ReportOpts -> Bool
period_ :: ReportOpts -> Period
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
real_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
sortspec_ :: ReportOpts -> SortSpec
statuses_ :: ReportOpts -> [Status]
summary_only_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
value_ :: ReportOpts -> Maybe ValuationType
period_ :: Period
interval_ :: Interval
statuses_ :: [Status]
conversionop_ :: Maybe ConversionOp
value_ :: Maybe ValuationType
infer_prices_ :: Bool
depth_ :: Maybe Int
date2_ :: Bool
empty_ :: Bool
no_elide_ :: Bool
real_ :: Bool
format_ :: StringFormat
pretty_ :: Bool
querystring_ :: [Text]
average_ :: Bool
related_ :: Bool
sortspec_ :: SortSpec
txn_dates_ :: Bool
balancecalc_ :: BalanceCalculation
balanceaccum_ :: BalanceAccumulation
budgetpat_ :: Maybe Text
accountlistmode_ :: AccountListMode
drop_ :: Int
declared_ :: Bool
row_total_ :: Bool
no_total_ :: Bool
summary_only_ :: Bool
show_costs_ :: Bool
sort_amount_ :: Bool
percent_ :: Bool
invert_ :: Bool
normalbalance_ :: Maybe NormalSign
color_ :: Bool
transpose_ :: Bool
layout_ :: Layout
..} (PeriodicReport [DateSpan]
colspans [PeriodicReportRow DisplayName Change]
items PeriodicReportRow () Change
tr) =
([Cell Text]
headers [Cell Text] -> [[Cell Text]] -> [[Cell Text]]
forall a. a -> [a] -> [a]
: (PeriodicReportRow DisplayName Change -> [[Cell Text]])
-> [PeriodicReportRow DisplayName Change] -> [[Cell Text]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap PeriodicReportRow DisplayName Change -> [[Cell Text]]
fullRowAsTexts [PeriodicReportRow DisplayName Change]
items,
([Cell Text] -> [Cell Text]) -> [[Cell Text]] -> [[Cell Text]]
forall a b. (a -> b) -> [a] -> [b]
map ((Cell Text -> Cell Text) -> [Cell Text] -> [Cell Text]
forall a b. (a -> b) -> [a] -> [b]
map (\Cell Text
c -> Cell Text
c{Ods.cellStyle = Ods.Body Ods.Total})) [[Cell Text]]
totalrows)
where
cell :: text -> Cell text
cell = text -> Cell text
forall text. text -> Cell text
Ods.defaultCell
headers :: [Cell Text]
headers =
(Text -> Cell Text) -> [Text] -> [Cell Text]
forall a b. (a -> b) -> [a] -> [b]
map (\Text
content -> (Text -> Cell Text
forall text. text -> Cell text
cell Text
content) {Ods.cellStyle = Ods.Head}) ([Text] -> [Cell Text]) -> [Text] -> [Cell Text]
forall a b. (a -> b) -> a -> b
$
Text
"account" Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:
case Layout
layout_ of
Layout
LayoutTidy -> [Text
"period", Text
"start_date", Text
"end_date", Text
"commodity", Text
"value"]
Layout
LayoutBare -> Text
"commodity" Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text]
dateHeaders
Layout
_ -> [Text]
dateHeaders
dateHeaders :: [Text]
dateHeaders = (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_]
fullRowAsTexts :: PeriodicReportRow DisplayName Change -> [[Cell Text]]
fullRowAsTexts PeriodicReportRow DisplayName Change
row = ([Cell Text] -> [Cell Text]) -> [[Cell Text]] -> [[Cell Text]]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> Cell Text
forall text. text -> Cell text
cell (PeriodicReportRow DisplayName Change -> Text
forall {a}. PeriodicReportRow DisplayName a -> Text
showName PeriodicReportRow DisplayName Change
row) Cell Text -> [Cell Text] -> [Cell Text]
forall a. a -> [a] -> [a]
:) ([[Cell Text]] -> [[Cell Text]]) -> [[Cell Text]] -> [[Cell Text]]
forall a b. (a -> b) -> a -> b
$ PeriodicReportRow DisplayName Change -> [[Cell Text]]
forall {a}. PeriodicReportRow a Change -> [[Cell Text]]
rowAsText PeriodicReportRow DisplayName Change
row
where showName :: PeriodicReportRow DisplayName a -> Text
showName = Int -> Text -> Text
accountNameDrop Int
drop_ (Text -> Text)
-> (PeriodicReportRow DisplayName a -> Text)
-> PeriodicReportRow DisplayName a
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PeriodicReportRow DisplayName a -> Text
forall {a}. PeriodicReportRow DisplayName a -> Text
prrFullName
totalrows :: [[Cell Text]]
totalrows
| Bool
no_total_ = []
| Bool
ishtml = (Cell Text -> [Cell Text] -> [Cell Text])
-> [Cell Text] -> [[Cell Text]] -> [[Cell Text]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (:) (Text -> Cell Text
forall text. text -> Cell text
cell Text
totalRowHeadingHtml Cell Text -> [Cell Text] -> [Cell Text]
forall a. a -> [a] -> [a]
: Cell Text -> [Cell Text]
forall a. a -> [a]
repeat Cell Text
forall text. Monoid text => Cell text
Ods.emptyCell) ([[Cell Text]] -> [[Cell Text]]) -> [[Cell Text]] -> [[Cell Text]]
forall a b. (a -> b) -> a -> b
$ PeriodicReportRow () Change -> [[Cell Text]]
forall {a}. PeriodicReportRow a Change -> [[Cell Text]]
rowAsText PeriodicReportRow () Change
tr
| Bool
otherwise = ([Cell Text] -> [Cell Text]) -> [[Cell Text]] -> [[Cell Text]]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> Cell Text
forall text. text -> Cell text
cell Text
totalRowHeadingCsv Cell Text -> [Cell Text] -> [Cell Text]
forall a. a -> [a] -> [a]
:) ([[Cell Text]] -> [[Cell Text]]) -> [[Cell Text]] -> [[Cell Text]]
forall a b. (a -> b) -> a -> b
$ PeriodicReportRow () Change -> [[Cell Text]]
forall {a}. PeriodicReportRow a Change -> [[Cell Text]]
rowAsText PeriodicReportRow () Change
tr
rowAsText :: PeriodicReportRow a Change -> [[Cell Text]]
rowAsText =
let fmt :: AmountFormat
fmt = if Bool
ishtml then AmountFormat
oneLineNoCostFmt else AmountFormat
machineFmt
in ([Cell WideBuilder] -> [Cell Text])
-> [[Cell WideBuilder]] -> [[Cell Text]]
forall a b. (a -> b) -> [a] -> [b]
map ((Cell WideBuilder -> Cell Text)
-> [Cell WideBuilder] -> [Cell Text]
forall a b. (a -> b) -> [a] -> [b]
map ((WideBuilder -> Text) -> Cell WideBuilder -> Cell Text
forall a b. (a -> b) -> Cell a -> Cell b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap WideBuilder -> Text
wbToText)) ([[Cell WideBuilder]] -> [[Cell Text]])
-> (PeriodicReportRow a Change -> [[Cell WideBuilder]])
-> PeriodicReportRow a Change
-> [[Cell Text]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AmountFormat
-> ReportOpts
-> [DateSpan]
-> PeriodicReportRow a Change
-> [[Cell WideBuilder]]
forall a.
AmountFormat
-> ReportOpts
-> [DateSpan]
-> PeriodicReportRow a Change
-> [[Cell WideBuilder]]
multiBalanceRowAsCellBuilders AmountFormat
fmt ReportOpts
opts [DateSpan]
colspans
stylesheet_ :: [(Text, Text)] -> result
stylesheet_ [(Text, Text)]
elstyles = Text -> result
forall arg result. TermRaw arg result => arg -> result
style_ (Text -> result) -> Text -> result
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
T.unlines ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ Text
"" Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text
elText -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>Text
" {"Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>Text
stylesText -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>Text
"}" | (Text
el,Text
styles) <- [(Text, Text)]
elstyles]
styles_ :: [Text] -> Attribute
styles_ = Text -> Attribute
forall arg result. TermRaw arg result => arg -> result
style_ (Text -> Attribute) -> ([Text] -> Text) -> [Text] -> Attribute
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text] -> Text
T.intercalate Text
"; "
bold :: Text
bold = Text
"font-weight:bold"
doubleborder :: Text
doubleborder = Text
"double black"
topdoubleborder :: Text
topdoubleborder = Text
"border-top:"Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>Text
doubleborder
bottomdoubleborder :: Text
bottomdoubleborder = Text
"border-bottom:"Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>Text
doubleborder
alignright :: Text
alignright = Text
"text-align:right"
alignleft :: Text
alignleft = Text
"text-align:left"
aligncenter :: CommandHelpStr
aligncenter = CommandHelpStr
"text-align:center"
collapse :: Text
collapse = Text
"border-collapse:collapse"
lpad :: Text
lpad = Text
"padding-left:1em"
rpad :: CommandHelpStr
rpad = CommandHelpStr
"padding-right:1em"
hpad :: CommandHelpStr
hpad = CommandHelpStr
"padding-left:1em; padding-right:1em"
vpad :: CommandHelpStr
vpad = CommandHelpStr
"padding-top:1em; padding-bottom:1em"
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 do
[(Text, Text)] -> Html ()
forall {result}. TermRaw Text result => [(Text, Text)] -> result
stylesheet_ [(Text
"table",Text
collapse), (Text
"th, td",Text
lpad), (Text
"th.account, td.account",Text
"padding-left:0;")]
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 = CommandHelpStr -> (CSV, CSV)
forall a. CommandHelpStr -> a
error' CommandHelpStr
"Sorry, --transpose with HTML output is not yet supported"
| Bool
otherwise = Bool -> ReportOpts -> MultiBalanceReport -> (CSV, CSV)
multiBalanceReportAsCsvHelper Bool
True 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
,((Bool -> [Text] -> Html ()) -> Bool -> [Text] -> Html ())
-> [Bool -> [Text] -> Html ()] -> [Bool] -> CSV -> [Html ()]
forall a b c d. (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
zipWith3 (Bool -> [Text] -> Html ()) -> Bool -> [Text] -> Html ()
forall a b. (a -> b) -> a -> b
($)
((Bool -> [Text] -> Html ()) -> [Bool -> [Text] -> Html ()]
forall a. a -> [a]
repeat (ReportOpts -> Bool -> [Text] -> Html ()
multiBalanceReportHtmlFootRow ReportOpts
ropts))
(Bool
True Bool -> [Bool] -> [Bool]
forall a. a -> [a] -> [a]
: Bool -> [Bool]
forall a. a -> [a]
repeat Bool
False)
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]
cells) =
let
([Text]
amts,[Text]
tot,[Text]
avg)
| ReportOpts -> Bool
row_total_ ReportOpts
ropts Bool -> Bool -> Bool
&& ReportOpts -> Bool
average_ ReportOpts
ropts = ([Text]
ini2, [Text]
sndlst2, [Text]
lst2)
| ReportOpts -> Bool
row_total_ ReportOpts
ropts = ([Text]
ini1, [Text]
lst1, [])
| ReportOpts -> Bool
average_ ReportOpts
ropts = ([Text]
ini1, [], [Text]
lst1)
| Bool
otherwise = ([Text]
cells, [], [])
where
n :: Int
n = [Text] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Text]
cells
([Text]
ini1,[Text]
lst1) = Int -> [Text] -> ([Text], [Text])
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [Text]
cells
([Text]
ini2, [Text]
rest) = Int -> [Text] -> ([Text], [Text])
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2) [Text]
cells
([Text]
sndlst2,[Text]
lst2) = Int -> [Text] -> ([Text], [Text])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
1 [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
styles_ [Text
bottomdoubleborder,Text
alignleft], Text -> Attribute
class_ Text
"account"] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> 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
styles_ [Text
bottomdoubleborder,Text
alignright], Text -> Attribute
class_ Text
""] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> 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
styles_ [Text
bottomdoubleborder,Text
alignright], Text -> Attribute
class_ Text
"rowtotal"] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> 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
styles_ [Text
bottomdoubleborder,Text
alignright], Text -> Attribute
class_ Text
"rowaverage"] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> 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]
cells) =
let
([Text]
amts,[Text]
tot,[Text]
avg)
| ReportOpts -> Bool
row_total_ ReportOpts
ropts Bool -> Bool -> Bool
&& ReportOpts -> Bool
average_ ReportOpts
ropts = ([Text]
ini2, [Text]
sndlst2, [Text]
lst2)
| ReportOpts -> Bool
row_total_ ReportOpts
ropts = ([Text]
ini1, [Text]
lst1, [])
| ReportOpts -> Bool
average_ ReportOpts
ropts = ([Text]
ini1, [], [Text]
lst1)
| Bool
otherwise = ([Text]
cells, [], [])
where
n :: Int
n = [Text] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Text]
cells
([Text]
ini1,[Text]
lst1) = Int -> [Text] -> ([Text], [Text])
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [Text]
cells
([Text]
ini2, [Text]
rest) = Int -> [Text] -> ([Text], [Text])
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2) [Text]
cells
([Text]
sndlst2,[Text]
lst2) = Int -> [Text] -> ([Text], [Text])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
1 [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
styles_ [], Text -> Attribute
class_ Text
"account"] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> 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
styles_ [Text
alignright], Text -> Attribute
class_ Text
"amount"] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> 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
styles_ [Text
alignright], Text -> Attribute
class_ Text
"amount rowtotal"] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> 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
styles_ [Text
alignright], Text -> Attribute
class_ Text
"amount rowaverage"] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> HtmlT m ()
toHtml Text
a) | Text
a <- [Text]
avg]
multiBalanceReportHtmlFootRow :: ReportOpts -> Bool -> [T.Text] -> Html ()
ReportOpts
_ Bool
_ [] = Html ()
forall a. Monoid a => a
mempty
multiBalanceReportHtmlFootRow ReportOpts
ropts Bool
isfirstline (Text
hdr:[Text]
cells) =
let
([Text]
amts,[Text]
tot,[Text]
avg)
| ReportOpts -> Bool
row_total_ ReportOpts
ropts Bool -> Bool -> Bool
&& ReportOpts -> Bool
average_ ReportOpts
ropts = ([Text]
ini2, [Text]
sndlst2, [Text]
lst2)
| ReportOpts -> Bool
row_total_ ReportOpts
ropts = ([Text]
ini1, [Text]
lst1, [])
| ReportOpts -> Bool
average_ ReportOpts
ropts = ([Text]
ini1, [], [Text]
lst1)
| Bool
otherwise = ([Text]
cells, [], [])
where
n :: Int
n = [Text] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Text]
cells
([Text]
ini1,[Text]
lst1) = Int -> [Text] -> ([Text], [Text])
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [Text]
cells
([Text]
ini2, [Text]
rest) = Int -> [Text] -> ([Text], [Text])
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2) [Text]
cells
([Text]
sndlst2,[Text]
lst2) = Int -> [Text] -> ([Text], [Text])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
1 [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
styles_ ([Text] -> Attribute) -> [Text] -> Attribute
forall a b. (a -> b) -> a -> b
$ [Text
topdoubleborder | Bool
isfirstline] [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text
bold], Text -> Attribute
class_ Text
"account"] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> HtmlT m ()
toHtml Text
hdr)
Html () -> [Html ()] -> [Html ()]
forall a. a -> [a] -> [a]
: [[Attribute] -> Html () -> Html ()
forall arg result. Term arg result => arg -> result
td_ [[Text] -> Attribute
styles_ ([Text] -> Attribute) -> [Text] -> Attribute
forall a b. (a -> b) -> a -> b
$ [Text
topdoubleborder | Bool
isfirstline] [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text
alignright], Text -> Attribute
class_ Text
"amount coltotal"] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> 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
styles_ ([Text] -> Attribute) -> [Text] -> Attribute
forall a b. (a -> b) -> a -> b
$ [Text
topdoubleborder | Bool
isfirstline] [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text
alignright], Text -> Attribute
class_ Text
"amount coltotal"] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> 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
styles_ ([Text] -> Attribute) -> [Text] -> Attribute
forall a b. (a -> b) -> a -> b
$ [Text
topdoubleborder | Bool
isfirstline] [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text
alignright], Text -> Attribute
class_ Text
"amount colaverage"] (Text -> Html ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
forall (m :: * -> *). Monad m => Text -> HtmlT m ()
toHtml Text
a) | Text
a <- [Text]
avg]
multiBalanceReportAsSpreadsheet ::
ReportOpts -> MultiBalanceReport -> ((Maybe Int, Maybe Int), [[Ods.Cell Text]])
multiBalanceReportAsSpreadsheet :: ReportOpts
-> MultiBalanceReport -> ((Maybe Int, Maybe Int), [[Cell Text]])
multiBalanceReportAsSpreadsheet ReportOpts
ropts MultiBalanceReport
mbr =
let ([[Cell Text]]
upper,[[Cell Text]]
lower) = Bool
-> ReportOpts
-> MultiBalanceReport
-> ([[Cell Text]], [[Cell Text]])
multiBalanceReportAsSpreadsheetHelper Bool
True ReportOpts
ropts MultiBalanceReport
mbr
in ((Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1, case ReportOpts -> Layout
layout_ ReportOpts
ropts of LayoutWide Maybe Int
_ -> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1; Layout
_ -> Maybe Int
forall a. Maybe a
Nothing),
[[Cell Text]]
upper [[Cell Text]] -> [[Cell Text]] -> [[Cell Text]]
forall a. [a] -> [a] -> [a]
++ [[Cell Text]]
lower)
multiBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> TL.Text
multiBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> Text
multiBalanceReportAsText ropts :: ReportOpts
ropts@ReportOpts{Bool
Int
[Text]
[Status]
SortSpec
Maybe Int
Maybe Text
Maybe NormalSign
Maybe ConversionOp
Maybe ValuationType
StringFormat
Interval
Period
AccountListMode
BalanceAccumulation
BalanceCalculation
Layout
accountlistmode_ :: ReportOpts -> AccountListMode
average_ :: ReportOpts -> Bool
balanceaccum_ :: ReportOpts -> BalanceAccumulation
balancecalc_ :: ReportOpts -> BalanceCalculation
budgetpat_ :: ReportOpts -> Maybe Text
color_ :: ReportOpts -> Bool
conversionop_ :: ReportOpts -> Maybe ConversionOp
date2_ :: ReportOpts -> Bool
declared_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
drop_ :: ReportOpts -> Int
empty_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
infer_prices_ :: ReportOpts -> Bool
interval_ :: ReportOpts -> Interval
invert_ :: ReportOpts -> Bool
layout_ :: ReportOpts -> Layout
no_elide_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
percent_ :: ReportOpts -> Bool
period_ :: ReportOpts -> Period
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
real_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
sortspec_ :: ReportOpts -> SortSpec
statuses_ :: ReportOpts -> [Status]
summary_only_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
value_ :: ReportOpts -> Maybe ValuationType
period_ :: Period
interval_ :: Interval
statuses_ :: [Status]
conversionop_ :: Maybe ConversionOp
value_ :: Maybe ValuationType
infer_prices_ :: Bool
depth_ :: Maybe Int
date2_ :: Bool
empty_ :: Bool
no_elide_ :: Bool
real_ :: Bool
format_ :: StringFormat
pretty_ :: Bool
querystring_ :: [Text]
average_ :: Bool
related_ :: Bool
sortspec_ :: SortSpec
txn_dates_ :: Bool
balancecalc_ :: BalanceCalculation
balanceaccum_ :: BalanceAccumulation
budgetpat_ :: Maybe Text
accountlistmode_ :: AccountListMode
drop_ :: Int
declared_ :: Bool
row_total_ :: Bool
no_total_ :: Bool
summary_only_ :: Bool
show_costs_ :: Bool
sort_amount_ :: Bool
percent_ :: Bool
invert_ :: Bool
normalbalance_ :: Maybe NormalSign
color_ :: Bool
transpose_ :: Bool
layout_ :: Layout
..} 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
multiBalanceReportTableAsText ReportOpts
ropts (ReportOpts -> MultiBalanceReport -> Table Text Text WideBuilder
multiBalanceReportAsTable 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 Maybe ConversionOp
conversionop_ of
Just ConversionOp
ToCost -> Text
", converted to cost"
Maybe ConversionOp
_ -> 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
multiBalanceReportTableAsText :: ReportOpts -> Table T.Text T.Text WideBuilder -> TB.Builder
multiBalanceReportTableAsText :: ReportOpts -> Table Text Text WideBuilder -> Builder
multiBalanceReportTableAsText ReportOpts{Bool
Int
[Text]
[Status]
SortSpec
Maybe Int
Maybe Text
Maybe NormalSign
Maybe ConversionOp
Maybe ValuationType
StringFormat
Interval
Period
AccountListMode
BalanceAccumulation
BalanceCalculation
Layout
accountlistmode_ :: ReportOpts -> AccountListMode
average_ :: ReportOpts -> Bool
balanceaccum_ :: ReportOpts -> BalanceAccumulation
balancecalc_ :: ReportOpts -> BalanceCalculation
budgetpat_ :: ReportOpts -> Maybe Text
color_ :: ReportOpts -> Bool
conversionop_ :: ReportOpts -> Maybe ConversionOp
date2_ :: ReportOpts -> Bool
declared_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
drop_ :: ReportOpts -> Int
empty_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
infer_prices_ :: ReportOpts -> Bool
interval_ :: ReportOpts -> Interval
invert_ :: ReportOpts -> Bool
layout_ :: ReportOpts -> Layout
no_elide_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
percent_ :: ReportOpts -> Bool
period_ :: ReportOpts -> Period
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
real_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
sortspec_ :: ReportOpts -> SortSpec
statuses_ :: ReportOpts -> [Status]
summary_only_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
value_ :: ReportOpts -> Maybe ValuationType
period_ :: Period
interval_ :: Interval
statuses_ :: [Status]
conversionop_ :: Maybe ConversionOp
value_ :: Maybe ValuationType
infer_prices_ :: Bool
depth_ :: Maybe Int
date2_ :: Bool
empty_ :: Bool
no_elide_ :: Bool
real_ :: Bool
format_ :: StringFormat
pretty_ :: Bool
querystring_ :: [Text]
average_ :: Bool
related_ :: Bool
sortspec_ :: SortSpec
txn_dates_ :: Bool
balancecalc_ :: BalanceCalculation
balanceaccum_ :: BalanceAccumulation
budgetpat_ :: Maybe Text
accountlistmode_ :: AccountListMode
drop_ :: Int
declared_ :: Bool
row_total_ :: Bool
no_total_ :: Bool
summary_only_ :: Bool
show_costs_ :: Bool
sort_amount_ :: Bool
percent_ :: Bool
invert_ :: Bool
normalbalance_ :: Maybe NormalSign
color_ :: Bool
transpose_ :: Bool
layout_ :: Layout
..} = TableOpts
-> ([Text] -> [Cell])
-> ((Text, [WideBuilder]) -> (Cell, [Cell]))
-> Table Text Text WideBuilder
-> Builder
forall a ch rh.
Show a =>
TableOpts
-> ([ch] -> [Cell])
-> ((rh, [a]) -> (Cell, [Cell]))
-> Table rh ch a
-> Builder
renderTableByRowsB TableOpts
tableopts [Text] -> [Cell]
renderCh (Text, [WideBuilder]) -> (Cell, [Cell])
renderRow
where
tableopts :: TableOpts
tableopts = TableOpts
forall a. Default a => a
def{tableBorders=multiColumnTableOuterBorder, prettyTable=pretty_}
multiColumnTableOuterBorder :: Bool
multiColumnTableOuterBorder = Bool
pretty_
renderCh :: [Text] -> [Cell]
renderCh :: [Text] -> [Cell]
renderCh
| Layout
layout_ Layout -> Layout -> Bool
forall a. Eq a => a -> a -> Bool
/= Layout
LayoutBare Bool -> Bool -> Bool
|| Bool
transpose_ = (Text -> Cell) -> [Text] -> [Cell]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Align -> Text -> Cell
textCell Align
TopRight)
| Bool
otherwise = ((Text -> Cell) -> Text -> Cell)
-> [Text -> Cell] -> [Text] -> [Cell]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Text -> Cell) -> Text -> Cell
forall a b. (a -> b) -> a -> b
($) (Align -> Text -> Cell
textCell Align
TopLeft (Text -> Cell) -> [Text -> Cell] -> [Text -> Cell]
forall a. a -> [a] -> [a]
: (Text -> Cell) -> [Text -> Cell]
forall a. a -> [a]
repeat (Align -> Text -> Cell
textCell Align
TopRight))
renderRow :: (Text, [WideBuilder]) -> (Cell, [Cell])
renderRow :: (Text, [WideBuilder]) -> (Cell, [Cell])
renderRow (Text
rh, [WideBuilder]
row)
| Layout
layout_ Layout -> Layout -> Bool
forall a. Eq a => a -> a -> Bool
/= Layout
LayoutBare Bool -> Bool -> Bool
|| Bool
transpose_ =
(Align -> Text -> Cell
textCell Align
TopLeft Text
rh, (WideBuilder -> Cell) -> [WideBuilder] -> [Cell]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Align -> [WideBuilder] -> Cell
Cell Align
TopRight ([WideBuilder] -> Cell)
-> (WideBuilder -> [WideBuilder]) -> WideBuilder -> Cell
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WideBuilder -> [WideBuilder]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure) [WideBuilder]
row)
| Bool
otherwise =
(Align -> Text -> Cell
textCell Align
TopLeft Text
rh, (([WideBuilder] -> Cell) -> [WideBuilder] -> Cell)
-> [[WideBuilder] -> Cell] -> [[WideBuilder]] -> [Cell]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith ([WideBuilder] -> Cell) -> [WideBuilder] -> Cell
forall a b. (a -> b) -> a -> b
($) (Align -> [WideBuilder] -> Cell
Cell Align
TopLeft ([WideBuilder] -> Cell)
-> [[WideBuilder] -> Cell] -> [[WideBuilder] -> Cell]
forall a. a -> [a] -> [a]
: ([WideBuilder] -> Cell) -> [[WideBuilder] -> Cell]
forall a. a -> [a]
repeat (Align -> [WideBuilder] -> Cell
Cell Align
TopRight)) ((WideBuilder -> [WideBuilder]) -> [WideBuilder] -> [[WideBuilder]]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap WideBuilder -> [WideBuilder]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [WideBuilder]
row))
multiBalanceReportAsTable :: ReportOpts -> MultiBalanceReport -> Table T.Text T.Text WideBuilder
multiBalanceReportAsTable :: ReportOpts -> MultiBalanceReport -> Table Text Text WideBuilder
multiBalanceReportAsTable opts :: ReportOpts
opts@ReportOpts{Bool
summary_only_ :: ReportOpts -> Bool
summary_only_ :: Bool
summary_only_, Bool
average_ :: ReportOpts -> Bool
average_ :: Bool
average_, Bool
row_total_ :: ReportOpts -> Bool
row_total_ :: Bool
row_total_, BalanceAccumulation
balanceaccum_ :: ReportOpts -> BalanceAccumulation
balanceaccum_ :: BalanceAccumulation
balanceaccum_}
(PeriodicReport [DateSpan]
spans [PeriodicReportRow DisplayName Change]
items PeriodicReportRow () Change
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
Group Properties
multiColumnTableInterRowBorder ([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
Header ([Text] -> [Header Text]) -> [Text] -> [Header Text]
forall a b. (a -> b) -> a -> b
$ 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
Group Properties
multiColumnTableInterColumnBorder ([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
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 -> Layout
layout_ ReportOpts
opts Layout -> Layout -> Bool
forall a. Eq a => a -> a -> Bool
== Layout
LayoutBare]
[Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ (if Bool -> Bool
not Bool
summary_only_ then (DateSpan -> Text) -> [DateSpan] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (BalanceAccumulation -> [DateSpan] -> DateSpan -> Text
reportPeriodName BalanceAccumulation
balanceaccum_ [DateSpan]
spans) [DateSpan]
spans else [])
[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 Change -> ([Text], [[WideBuilder]])
fullRowAsTexts PeriodicReportRow DisplayName Change
row =
let rs :: [[WideBuilder]]
rs = ReportOpts
-> PeriodicReportRow DisplayName Change -> [[WideBuilder]]
forall a.
ReportOpts -> PeriodicReportRow a Change -> [[WideBuilder]]
multiBalanceRowAsText ReportOpts
opts PeriodicReportRow DisplayName Change
row
in (Int -> Text -> [Text]
forall a. Int -> a -> [a]
replicate ([[WideBuilder]] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[WideBuilder]]
rs) (PeriodicReportRow DisplayName Change -> Text
forall {a}. PeriodicReportRow DisplayName a -> Text
renderacct PeriodicReportRow DisplayName Change
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 Change -> ([Text], [[WideBuilder]]))
-> [PeriodicReportRow DisplayName Change]
-> [([Text], [[WideBuilder]])]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap PeriodicReportRow DisplayName Change -> ([Text], [[WideBuilder]])
fullRowAsTexts [PeriodicReportRow DisplayName Change]
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 () Change -> [[WideBuilder]]
forall a.
ReportOpts -> PeriodicReportRow a Change -> [[WideBuilder]]
multiBalanceRowAsText ReportOpts
opts PeriodicReportRow () Change
tr
rowhdrs :: Header Text
rowhdrs = Properties -> [Header Text] -> Header Text
forall h. Properties -> [Header h] -> Header h
Group Properties
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
Header ([Text] -> [Header Text]) -> [Text] -> [Header Text]
forall a b. (a -> b) -> a -> b
$ Text
totalRowHeadingText Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: Int -> Text -> [Text]
forall a. Int -> a -> [a]
replicate ([[WideBuilder]] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[WideBuilder]]
totalrows Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Text
""
colhdrs :: Header [a]
colhdrs = [a] -> Header [a]
forall h. h -> Header h
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
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
rowhdrs Header [Any]
forall {a}. Header [a]
colhdrs [[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
multiColumnTableInterRowBorder :: Properties
multiColumnTableInterRowBorder = Properties
NoLine
multiColumnTableInterColumnBorder :: Properties
multiColumnTableInterColumnBorder = if ReportOpts -> Bool
pretty_ ReportOpts
opts then Properties
SingleLine else Properties
NoLine
multiBalanceRowAsTextBuilders :: AmountFormat -> ReportOpts -> [DateSpan] -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
multiBalanceRowAsTextBuilders :: forall a.
AmountFormat
-> ReportOpts
-> [DateSpan]
-> PeriodicReportRow a Change
-> [[WideBuilder]]
multiBalanceRowAsTextBuilders AmountFormat
bopts ReportOpts
ropts [DateSpan]
colspans PeriodicReportRow a Change
row =
([Cell WideBuilder] -> [WideBuilder])
-> [[Cell WideBuilder]] -> [[WideBuilder]]
forall a b. (a -> b) -> [a] -> [b]
map ((Cell WideBuilder -> WideBuilder)
-> [Cell WideBuilder] -> [WideBuilder]
forall a b. (a -> b) -> [a] -> [b]
map Cell WideBuilder -> WideBuilder
forall text. Cell text -> text
Ods.cellContent) ([[Cell WideBuilder]] -> [[WideBuilder]])
-> [[Cell WideBuilder]] -> [[WideBuilder]]
forall a b. (a -> b) -> a -> b
$
AmountFormat
-> ReportOpts
-> [DateSpan]
-> PeriodicReportRow a Change
-> [[Cell WideBuilder]]
forall a.
AmountFormat
-> ReportOpts
-> [DateSpan]
-> PeriodicReportRow a Change
-> [[Cell WideBuilder]]
multiBalanceRowAsCellBuilders AmountFormat
bopts ReportOpts
ropts [DateSpan]
colspans PeriodicReportRow a Change
row
multiBalanceRowAsCellBuilders ::
AmountFormat -> ReportOpts -> [DateSpan] -> PeriodicReportRow a MixedAmount -> [[Ods.Cell WideBuilder]]
multiBalanceRowAsCellBuilders :: forall a.
AmountFormat
-> ReportOpts
-> [DateSpan]
-> PeriodicReportRow a Change
-> [[Cell WideBuilder]]
multiBalanceRowAsCellBuilders AmountFormat
bopts ReportOpts{Bool
Int
[Text]
[Status]
SortSpec
Maybe Int
Maybe Text
Maybe NormalSign
Maybe ConversionOp
Maybe ValuationType
StringFormat
Interval
Period
AccountListMode
BalanceAccumulation
BalanceCalculation
Layout
accountlistmode_ :: ReportOpts -> AccountListMode
average_ :: ReportOpts -> Bool
balanceaccum_ :: ReportOpts -> BalanceAccumulation
balancecalc_ :: ReportOpts -> BalanceCalculation
budgetpat_ :: ReportOpts -> Maybe Text
color_ :: ReportOpts -> Bool
conversionop_ :: ReportOpts -> Maybe ConversionOp
date2_ :: ReportOpts -> Bool
declared_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
drop_ :: ReportOpts -> Int
empty_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
infer_prices_ :: ReportOpts -> Bool
interval_ :: ReportOpts -> Interval
invert_ :: ReportOpts -> Bool
layout_ :: ReportOpts -> Layout
no_elide_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
percent_ :: ReportOpts -> Bool
period_ :: ReportOpts -> Period
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
real_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
sortspec_ :: ReportOpts -> SortSpec
statuses_ :: ReportOpts -> [Status]
summary_only_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
value_ :: ReportOpts -> Maybe ValuationType
period_ :: Period
interval_ :: Interval
statuses_ :: [Status]
conversionop_ :: Maybe ConversionOp
value_ :: Maybe ValuationType
infer_prices_ :: Bool
depth_ :: Maybe Int
date2_ :: Bool
empty_ :: Bool
no_elide_ :: Bool
real_ :: Bool
format_ :: StringFormat
pretty_ :: Bool
querystring_ :: [Text]
average_ :: Bool
related_ :: Bool
sortspec_ :: SortSpec
txn_dates_ :: Bool
balancecalc_ :: BalanceCalculation
balanceaccum_ :: BalanceAccumulation
budgetpat_ :: Maybe Text
accountlistmode_ :: AccountListMode
drop_ :: Int
declared_ :: Bool
row_total_ :: Bool
no_total_ :: Bool
summary_only_ :: Bool
show_costs_ :: Bool
sort_amount_ :: Bool
percent_ :: Bool
invert_ :: Bool
normalbalance_ :: Maybe NormalSign
color_ :: Bool
transpose_ :: Bool
layout_ :: Layout
..} [DateSpan]
colspans (PeriodicReportRow a
_ [Change]
as Change
rowtot Change
rowavg) =
case Layout
layout_ of
LayoutWide Maybe Int
width -> [(Change -> Cell WideBuilder) -> [Change] -> [Cell WideBuilder]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (AmountFormat -> Change -> Cell WideBuilder
cellFromMixedAmount AmountFormat
bopts{displayMaxWidth=width}) [Change]
allamts]
Layout
LayoutTall -> Cell WideBuilder -> [[Cell WideBuilder]] -> [[Cell WideBuilder]]
forall a. a -> [[a]] -> [[a]]
paddedTranspose Cell WideBuilder
forall text. Monoid text => Cell text
Ods.emptyCell
([[Cell WideBuilder]] -> [[Cell WideBuilder]])
-> ([Change] -> [[Cell WideBuilder]])
-> [Change]
-> [[Cell WideBuilder]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Change -> [Cell WideBuilder]) -> [Change] -> [[Cell WideBuilder]]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (AmountFormat -> Change -> [Cell WideBuilder]
cellsFromMixedAmount AmountFormat
bopts{displayMaxWidth=Nothing})
([Change] -> [[Cell WideBuilder]])
-> [Change] -> [[Cell WideBuilder]]
forall a b. (a -> b) -> a -> b
$ [Change]
allamts
Layout
LayoutBare -> (Cell WideBuilder -> [Cell WideBuilder] -> [Cell WideBuilder])
-> [Cell WideBuilder]
-> [[Cell WideBuilder]]
-> [[Cell WideBuilder]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (:) ((Text -> Cell WideBuilder) -> [Text] -> [Cell WideBuilder]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Cell WideBuilder
wbCell [Text]
cs)
([[Cell WideBuilder]] -> [[Cell WideBuilder]])
-> ([Change] -> [[Cell WideBuilder]])
-> [Change]
-> [[Cell WideBuilder]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Cell WideBuilder]] -> [[Cell WideBuilder]]
forall a. [[a]] -> [[a]]
transpose
([[Cell WideBuilder]] -> [[Cell WideBuilder]])
-> ([Change] -> [[Cell WideBuilder]])
-> [Change]
-> [[Cell WideBuilder]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Change -> [Cell WideBuilder]) -> [Change] -> [[Cell WideBuilder]]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (AmountFormat -> Change -> [Cell WideBuilder]
cellsFromMixedAmount AmountFormat
bopts{displayCommodity=False, displayCommodityOrder=Just cs, displayMinWidth=Nothing})
([Change] -> [[Cell WideBuilder]])
-> [Change] -> [[Cell WideBuilder]]
forall a b. (a -> b) -> a -> b
$ [Change]
allamts
Layout
LayoutTidy -> [[[Cell WideBuilder]]] -> [[Cell WideBuilder]]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
([[[Cell WideBuilder]]] -> [[Cell WideBuilder]])
-> ([Change] -> [[[Cell WideBuilder]]])
-> [Change]
-> [[Cell WideBuilder]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (DateSpan -> [[Cell WideBuilder]] -> [[Cell WideBuilder]])
-> [DateSpan] -> [[[Cell WideBuilder]]] -> [[[Cell WideBuilder]]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (([Cell WideBuilder] -> [Cell WideBuilder])
-> [[Cell WideBuilder]] -> [[Cell WideBuilder]]
forall a b. (a -> b) -> [a] -> [b]
map (([Cell WideBuilder] -> [Cell WideBuilder])
-> [[Cell WideBuilder]] -> [[Cell WideBuilder]])
-> (DateSpan -> [Cell WideBuilder] -> [Cell WideBuilder])
-> DateSpan
-> [[Cell WideBuilder]]
-> [[Cell WideBuilder]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DateSpan -> [Cell WideBuilder] -> [Cell WideBuilder]
addDateColumns) [DateSpan]
colspans
([[[Cell WideBuilder]]] -> [[[Cell WideBuilder]]])
-> ([Change] -> [[[Cell WideBuilder]]])
-> [Change]
-> [[[Cell WideBuilder]]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Change -> [[Cell WideBuilder]])
-> [Change] -> [[[Cell WideBuilder]]]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ( (Text -> Cell WideBuilder -> [Cell WideBuilder])
-> [Text] -> [Cell WideBuilder] -> [[Cell WideBuilder]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Text
c Cell WideBuilder
a -> [Text -> Cell WideBuilder
wbCell Text
c, Cell WideBuilder
a]) [Text]
cs
([Cell WideBuilder] -> [[Cell WideBuilder]])
-> (Change -> [Cell WideBuilder]) -> Change -> [[Cell WideBuilder]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AmountFormat -> Change -> [Cell WideBuilder]
cellsFromMixedAmount AmountFormat
bopts{displayCommodity=False, displayCommodityOrder=Just cs, displayMinWidth=Nothing})
([Change] -> [[Cell WideBuilder]])
-> [Change] -> [[Cell WideBuilder]]
forall a b. (a -> b) -> a -> b
$ [Change]
as
where
wbCell :: Text -> Cell WideBuilder
wbCell = WideBuilder -> Cell WideBuilder
forall text. text -> Cell text
Ods.defaultCell (WideBuilder -> Cell WideBuilder)
-> (Text -> WideBuilder) -> Text -> Cell WideBuilder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> WideBuilder
wbFromText
wbDate :: Text -> Cell WideBuilder
wbDate Text
content = (Text -> Cell WideBuilder
wbCell Text
content) {Ods.cellType = Ods.TypeDate}
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 = if (Change -> Bool) -> [Change] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Change -> Bool
mixedAmountLooksZero [Change]
allamts then [Text
""] else Set Text -> [Text]
forall a. Set a -> [a]
S.toList (Set Text -> [Text]) -> Set Text -> [Text]
forall a b. (a -> b) -> a -> b
$ (Change -> Set Text) -> [Change] -> Set Text
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Change -> Set Text
maCommodities [Change]
allamts
allamts :: [Change]
allamts = (if Bool -> Bool
not Bool
summary_only_ then [Change]
as else []) [Change] -> [Change] -> [Change]
forall a. [a] -> [a] -> [a]
++
[Change
rowtot | Bool
totalscolumn Bool -> Bool -> Bool
&& Bool -> Bool
not ([Change] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Change]
as)] [Change] -> [Change] -> [Change]
forall a. [a] -> [a] -> [a]
++
[Change
rowavg | Bool
average_ Bool -> Bool -> Bool
&& Bool -> Bool
not ([Change] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Change]
as)]
addDateColumns :: DateSpan -> [Cell WideBuilder] -> [Cell WideBuilder]
addDateColumns spn :: DateSpan
spn@(DateSpan Maybe EFDay
s Maybe EFDay
e) = (Text -> Cell WideBuilder
wbCell (DateSpan -> Text
showDateSpan DateSpan
spn) Cell WideBuilder -> [Cell WideBuilder] -> [Cell WideBuilder]
forall a. a -> [a] -> [a]
:)
([Cell WideBuilder] -> [Cell WideBuilder])
-> ([Cell WideBuilder] -> [Cell WideBuilder])
-> [Cell WideBuilder]
-> [Cell WideBuilder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Cell WideBuilder
wbDate (Text -> (EFDay -> Text) -> Maybe EFDay -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" EFDay -> Text
showEFDate Maybe EFDay
s) Cell WideBuilder -> [Cell WideBuilder] -> [Cell WideBuilder]
forall a. a -> [a] -> [a]
:)
([Cell WideBuilder] -> [Cell WideBuilder])
-> ([Cell WideBuilder] -> [Cell WideBuilder])
-> [Cell WideBuilder]
-> [Cell WideBuilder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Cell WideBuilder
wbDate (Text -> (EFDay -> Text) -> Maybe EFDay -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (EFDay -> Text
showEFDate (EFDay -> Text) -> (EFDay -> EFDay) -> EFDay -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Day -> Day) -> EFDay -> EFDay
modifyEFDay (Integer -> Day -> Day
addDays (-Integer
1))) Maybe EFDay
e) Cell WideBuilder -> [Cell WideBuilder] -> [Cell WideBuilder]
forall a. a -> [a] -> [a]
:)
paddedTranspose :: a -> [[a]] -> [[a]]
paddedTranspose :: forall a. a -> [[a]] -> [[a]]
paddedTranspose a
_ [] = [[]]
paddedTranspose a
n [[a]]
as1 = Int -> [[a]] -> [[a]]
forall a. Int -> [a] -> [a]
take ([Int] -> Int
forall a. Ord a => [a] -> a
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 a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([[a]] -> Int) -> [[a]] -> Int
forall a b. (a -> b) -> a -> b
$ [[a]]
as1) ([[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]]
as1
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]
multiBalanceRowAsText :: ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
multiBalanceRowAsText :: forall a.
ReportOpts -> PeriodicReportRow a Change -> [[WideBuilder]]
multiBalanceRowAsText ReportOpts
opts = AmountFormat
-> ReportOpts
-> [DateSpan]
-> PeriodicReportRow a Change
-> [[WideBuilder]]
forall a.
AmountFormat
-> ReportOpts
-> [DateSpan]
-> PeriodicReportRow a Change
-> [[WideBuilder]]
multiBalanceRowAsTextBuilders AmountFormat
oneLineNoCostFmt{displayColour=color_ opts} ReportOpts
opts []
multiBalanceRowAsCsvText :: ReportOpts -> [DateSpan] -> PeriodicReportRow a MixedAmount -> [[T.Text]]
multiBalanceRowAsCsvText :: forall a.
ReportOpts -> [DateSpan] -> PeriodicReportRow a Change -> CSV
multiBalanceRowAsCsvText ReportOpts
opts [DateSpan]
colspans = ([WideBuilder] -> [Text]) -> [[WideBuilder]] -> CSV
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((WideBuilder -> Text) -> [WideBuilder] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap WideBuilder -> Text
wbToText) ([[WideBuilder]] -> CSV)
-> (PeriodicReportRow a Change -> [[WideBuilder]])
-> PeriodicReportRow a Change
-> CSV
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AmountFormat
-> ReportOpts
-> [DateSpan]
-> PeriodicReportRow a Change
-> [[WideBuilder]]
forall a.
AmountFormat
-> ReportOpts
-> [DateSpan]
-> PeriodicReportRow a Change
-> [[WideBuilder]]
multiBalanceRowAsTextBuilders AmountFormat
machineFmt ReportOpts
opts [DateSpan]
colspans
type BudgetDisplayCell = (WideBuilder, Maybe (WideBuilder, Maybe WideBuilder))
type BudgetDisplayRow = [BudgetDisplayCell]
type BudgetShowAmountsFn = MixedAmount -> [WideBuilder]
type BudgetCalcPercentagesFn = Change -> BudgetGoal -> [Maybe Percentage]
budgetReportAsText :: ReportOpts -> BudgetReport -> TL.Text
budgetReportAsText :: ReportOpts -> BudgetReport -> Text
budgetReportAsText ropts :: ReportOpts
ropts@ReportOpts{Bool
Int
[Text]
[Status]
SortSpec
Maybe Int
Maybe Text
Maybe NormalSign
Maybe ConversionOp
Maybe ValuationType
StringFormat
Interval
Period
AccountListMode
BalanceAccumulation
BalanceCalculation
Layout
accountlistmode_ :: ReportOpts -> AccountListMode
average_ :: ReportOpts -> Bool
balanceaccum_ :: ReportOpts -> BalanceAccumulation
balancecalc_ :: ReportOpts -> BalanceCalculation
budgetpat_ :: ReportOpts -> Maybe Text
color_ :: ReportOpts -> Bool
conversionop_ :: ReportOpts -> Maybe ConversionOp
date2_ :: ReportOpts -> Bool
declared_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
drop_ :: ReportOpts -> Int
empty_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
infer_prices_ :: ReportOpts -> Bool
interval_ :: ReportOpts -> Interval
invert_ :: ReportOpts -> Bool
layout_ :: ReportOpts -> Layout
no_elide_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
percent_ :: ReportOpts -> Bool
period_ :: ReportOpts -> Period
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
real_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
sortspec_ :: ReportOpts -> SortSpec
statuses_ :: ReportOpts -> [Status]
summary_only_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
value_ :: ReportOpts -> Maybe ValuationType
period_ :: Period
interval_ :: Interval
statuses_ :: [Status]
conversionop_ :: Maybe ConversionOp
value_ :: Maybe ValuationType
infer_prices_ :: Bool
depth_ :: Maybe Int
date2_ :: Bool
empty_ :: Bool
no_elide_ :: Bool
real_ :: Bool
format_ :: StringFormat
pretty_ :: Bool
querystring_ :: [Text]
average_ :: Bool
related_ :: Bool
sortspec_ :: SortSpec
txn_dates_ :: Bool
balancecalc_ :: BalanceCalculation
balanceaccum_ :: BalanceAccumulation
budgetpat_ :: Maybe Text
accountlistmode_ :: AccountListMode
drop_ :: Int
declared_ :: Bool
row_total_ :: Bool
no_total_ :: Bool
summary_only_ :: Bool
show_costs_ :: Bool
sort_amount_ :: Bool
percent_ :: Bool
invert_ :: Bool
normalbalance_ :: Maybe NormalSign
color_ :: Bool
transpose_ :: Bool
layout_ :: Layout
..} BudgetReport
budgetr = 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
multiBalanceReportTableAsText ReportOpts
ropts (ReportOpts -> BudgetReport -> Table Text Text WideBuilder
budgetReportAsTable ReportOpts
ropts BudgetReport
budgetr)
where
title :: Text
title = Text
"Budget performance in " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> DateSpan -> Text
showDateSpan (BudgetReport -> DateSpan
forall a b. PeriodicReport a b -> DateSpan
periodicReportSpan BudgetReport
budgetr)
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (case Maybe ConversionOp
conversionop_ of
Just ConversionOp
ToCost -> Text
", converted to cost"
Maybe ConversionOp
_ -> 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) -> 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
"")
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
":"
budgetReportAsTable :: ReportOpts -> BudgetReport -> Table Text Text WideBuilder
budgetReportAsTable :: ReportOpts -> BudgetReport -> Table Text Text WideBuilder
budgetReportAsTable ReportOpts{Bool
Int
[Text]
[Status]
SortSpec
Maybe Int
Maybe Text
Maybe NormalSign
Maybe ConversionOp
Maybe ValuationType
StringFormat
Interval
Period
AccountListMode
BalanceAccumulation
BalanceCalculation
Layout
accountlistmode_ :: ReportOpts -> AccountListMode
average_ :: ReportOpts -> Bool
balanceaccum_ :: ReportOpts -> BalanceAccumulation
balancecalc_ :: ReportOpts -> BalanceCalculation
budgetpat_ :: ReportOpts -> Maybe Text
color_ :: ReportOpts -> Bool
conversionop_ :: ReportOpts -> Maybe ConversionOp
date2_ :: ReportOpts -> Bool
declared_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
drop_ :: ReportOpts -> Int
empty_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
infer_prices_ :: ReportOpts -> Bool
interval_ :: ReportOpts -> Interval
invert_ :: ReportOpts -> Bool
layout_ :: ReportOpts -> Layout
no_elide_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
percent_ :: ReportOpts -> Bool
period_ :: ReportOpts -> Period
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
real_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
sortspec_ :: ReportOpts -> SortSpec
statuses_ :: ReportOpts -> [Status]
summary_only_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
value_ :: ReportOpts -> Maybe ValuationType
period_ :: Period
interval_ :: Interval
statuses_ :: [Status]
conversionop_ :: Maybe ConversionOp
value_ :: Maybe ValuationType
infer_prices_ :: Bool
depth_ :: Maybe Int
date2_ :: Bool
empty_ :: Bool
no_elide_ :: Bool
real_ :: Bool
format_ :: StringFormat
pretty_ :: Bool
querystring_ :: [Text]
average_ :: Bool
related_ :: Bool
sortspec_ :: SortSpec
txn_dates_ :: Bool
balancecalc_ :: BalanceCalculation
balanceaccum_ :: BalanceAccumulation
budgetpat_ :: Maybe Text
accountlistmode_ :: AccountListMode
drop_ :: Int
declared_ :: Bool
row_total_ :: Bool
no_total_ :: Bool
summary_only_ :: Bool
show_costs_ :: Bool
sort_amount_ :: Bool
percent_ :: Bool
invert_ :: Bool
normalbalance_ :: Maybe NormalSign
color_ :: Bool
transpose_ :: Bool
layout_ :: Layout
..} (PeriodicReport [DateSpan]
spans [PeriodicReportRow DisplayName (Maybe Change, Maybe Change)]
items PeriodicReportRow () (Maybe Change, Maybe Change)
totrow) =
Table Text Text WideBuilder -> Table Text Text WideBuilder
forall {rh} {a}. Table rh rh a -> Table rh rh a
maybetransposetable (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
Group Properties
budgetTableInterRowBorder ([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
Header [Text]
accts)
(Properties -> [Header Text] -> Header Text
forall h. Properties -> [Header h] -> Header h
Group Properties
budgetTableInterColumnBorder ([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
Header [Text]
colheadings)
[[WideBuilder]]
rows
where
budgetTableInterRowBorder :: Properties
budgetTableInterRowBorder = Properties
NoLine
budgetTableInterColumnBorder :: Properties
budgetTableInterColumnBorder = if Bool
pretty_ then Properties
SingleLine else Properties
NoLine
maybetransposetable :: Table rh rh a -> Table rh rh a
maybetransposetable
| Bool
transpose_ = \(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
addtotalrow :: Table Text ch WideBuilder -> Table Text ch WideBuilder
addtotalrow
| Bool
no_total_ = Table Text ch WideBuilder -> Table Text ch WideBuilder
forall a. a -> a
id
| Bool
otherwise =
let
rowhdrs :: Header Text
rowhdrs = Properties -> [Header Text] -> Header Text
forall h. Properties -> [Header h] -> Header h
Group Properties
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
Header ([Text] -> [Header Text]) -> [Text] -> [Header Text]
forall a b. (a -> b) -> a -> b
$ Text
totalRowHeadingBudgetText Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: Int -> Text -> [Text]
forall a. Int -> a -> [a]
replicate ([[WideBuilder]] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[WideBuilder]]
totalrows Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Text
""
colhdrs :: Header [a]
colhdrs = [a] -> Header [a]
forall h. h -> Header h
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
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
rowhdrs Header [Any]
forall {a}. Header [a]
colhdrs [[WideBuilder]]
totalrows)
colheadings :: [Text]
colheadings = [Text
"Commodity" | Layout
layout_ Layout -> Layout -> Bool
forall a. Eq a => a -> a -> Bool
== Layout
LayoutBare]
[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
row_total_]
[Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text
"Average" | Bool
average_]
([Text]
accts, [[WideBuilder]]
rows, [[WideBuilder]]
totalrows) =
([Text]
accts'
,[WideBuilder] -> [[WideBuilder]] -> [[WideBuilder]]
maybecommcol [WideBuilder]
itemscs ([[WideBuilder]] -> [[WideBuilder]])
-> [[WideBuilder]] -> [[WideBuilder]]
forall a b. (a -> b) -> a -> b
$ [[BudgetDisplayCell]] -> [[WideBuilder]]
showcells [[BudgetDisplayCell]]
texts
,[WideBuilder] -> [[WideBuilder]] -> [[WideBuilder]]
maybecommcol [WideBuilder]
totrowcs ([[WideBuilder]] -> [[WideBuilder]])
-> [[WideBuilder]] -> [[WideBuilder]]
forall a b. (a -> b) -> a -> b
$ [[BudgetDisplayCell]] -> [[WideBuilder]]
showtotrow [[BudgetDisplayCell]]
totrowtexts)
where
maybecommcol :: [WideBuilder] -> [[WideBuilder]] -> [[WideBuilder]]
maybecommcol :: [WideBuilder] -> [[WideBuilder]] -> [[WideBuilder]]
maybecommcol [WideBuilder]
cs
| Layout
layout_ Layout -> Layout -> Bool
forall a. Eq a => a -> a -> Bool
== Layout
LayoutBare = (WideBuilder -> [WideBuilder] -> [WideBuilder])
-> [WideBuilder] -> [[WideBuilder]] -> [[WideBuilder]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (:) [WideBuilder]
cs
| Bool
otherwise = [[WideBuilder]] -> [[WideBuilder]]
forall a. a -> a
id
showcells, showtotrow :: [[BudgetDisplayCell]] -> [[WideBuilder]]
([[BudgetDisplayCell]] -> [[WideBuilder]]
showcells, [[BudgetDisplayCell]] -> [[WideBuilder]]
showtotrow) =
([[WideBuilder]] -> [[WideBuilder]]
forall a. [[a]] -> [[a]]
maybetranspose ([[WideBuilder]] -> [[WideBuilder]])
-> ([[BudgetDisplayCell]] -> [[WideBuilder]])
-> [[BudgetDisplayCell]]
-> [[WideBuilder]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([BudgetDisplayCell] -> [WideBuilder])
-> [[BudgetDisplayCell]] -> [[WideBuilder]]
forall a b. (a -> b) -> [a] -> [b]
map (((Int, Int, Int) -> BudgetDisplayCell -> WideBuilder)
-> [(Int, Int, Int)] -> [BudgetDisplayCell] -> [WideBuilder]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Int, Int, Int) -> BudgetDisplayCell -> WideBuilder
showBudgetDisplayCell [(Int, Int, Int)]
widths) ([[BudgetDisplayCell]] -> [[WideBuilder]])
-> ([[BudgetDisplayCell]] -> [[BudgetDisplayCell]])
-> [[BudgetDisplayCell]]
-> [[WideBuilder]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[BudgetDisplayCell]] -> [[BudgetDisplayCell]]
forall a. [[a]] -> [[a]]
maybetranspose
,[[WideBuilder]] -> [[WideBuilder]]
forall a. [[a]] -> [[a]]
maybetranspose ([[WideBuilder]] -> [[WideBuilder]])
-> ([[BudgetDisplayCell]] -> [[WideBuilder]])
-> [[BudgetDisplayCell]]
-> [[WideBuilder]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([BudgetDisplayCell] -> [WideBuilder])
-> [[BudgetDisplayCell]] -> [[WideBuilder]]
forall a b. (a -> b) -> [a] -> [b]
map (((Int, Int, Int) -> BudgetDisplayCell -> WideBuilder)
-> [(Int, Int, Int)] -> [BudgetDisplayCell] -> [WideBuilder]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Int, Int, Int) -> BudgetDisplayCell -> WideBuilder
showBudgetDisplayCell [(Int, Int, Int)]
totrowwidths) ([[BudgetDisplayCell]] -> [[WideBuilder]])
-> ([[BudgetDisplayCell]] -> [[BudgetDisplayCell]])
-> [[BudgetDisplayCell]]
-> [[WideBuilder]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[BudgetDisplayCell]] -> [[BudgetDisplayCell]]
forall a. [[a]] -> [[a]]
maybetranspose)
where
showBudgetDisplayCell :: (Int, Int, Int) -> BudgetDisplayCell -> WideBuilder
showBudgetDisplayCell :: (Int, Int, Int) -> BudgetDisplayCell -> WideBuilder
showBudgetDisplayCell (Int
actualwidth, Int
budgetwidth, Int
percentwidth) (WideBuilder
actual, Maybe (WideBuilder, Maybe WideBuilder)
mbudget) =
(Builder -> Int -> WideBuilder) -> Int -> Builder -> WideBuilder
forall a b c. (a -> b -> c) -> b -> a -> c
flip Builder -> Int -> WideBuilder
WideBuilder (Int
actualwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
totalbudgetwidth) (Builder -> WideBuilder) -> Builder -> WideBuilder
forall a b. (a -> b) -> a -> b
$
WideBuilder -> Builder
toPadded WideBuilder
actual Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
-> ((WideBuilder, Maybe WideBuilder) -> Builder)
-> Maybe (WideBuilder, Maybe WideBuilder)
-> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
emptycell (WideBuilder, Maybe WideBuilder) -> Builder
showBudgetGoalAndPercentage Maybe (WideBuilder, Maybe WideBuilder)
mbudget
where
toPadded :: WideBuilder -> Builder
toPadded (WideBuilder Builder
b Int
w) = (Text -> Builder
TB.fromText (Text -> Builder) -> (Int -> Text) -> Int -> Builder
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 -> Builder) -> Int -> Builder
forall a b. (a -> b) -> a -> b
$ Int
actualwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
w) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
b
(Int
totalpercentwidth, Int
totalbudgetwidth) =
let totalpercentwidth' :: Int
totalpercentwidth' = if Int
percentwidth Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Int
0 else Int
percentwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
5
in ( Int
totalpercentwidth'
, if Int
budgetwidth Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Int
0 else Int
budgetwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
totalpercentwidth' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
3
)
emptycell :: TB.Builder
emptycell :: Builder
emptycell = Text -> Builder
TB.fromText (Text -> Builder) -> Text -> Builder
forall a b. (a -> b) -> a -> b
$ Int -> Text -> Text
T.replicate Int
totalbudgetwidth Text
" "
showBudgetGoalAndPercentage :: (WideBuilder, Maybe WideBuilder) -> TB.Builder
showBudgetGoalAndPercentage :: (WideBuilder, Maybe WideBuilder) -> Builder
showBudgetGoalAndPercentage (WideBuilder
goal, Maybe WideBuilder
perc) =
let perct :: Text
perct = case Maybe WideBuilder
perc of
Maybe WideBuilder
Nothing -> Int -> Text -> Text
T.replicate Int
totalpercentwidth Text
" "
Just WideBuilder
pct -> Int -> Text -> Text
T.replicate (Int
percentwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
- WideBuilder -> Int
wbWidth WideBuilder
pct) Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> WideBuilder -> Text
wbToText WideBuilder
pct Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"% of "
in Text -> Builder
TB.fromText (Text -> Builder) -> Text -> Builder
forall a b. (a -> b) -> a -> b
$ Text
" [" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
perct Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text -> Text
T.replicate (Int
budgetwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
- WideBuilder -> Int
wbWidth WideBuilder
goal) Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> WideBuilder -> Text
wbToText WideBuilder
goal Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"]"
widths :: [(Int, Int, Int)]
widths :: [(Int, Int, Int)]
widths = [Int] -> [Int] -> [Int] -> [(Int, Int, Int)]
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 [Int]
actualwidths [Int]
budgetwidths [Int]
percentwidths
where
actualwidths :: [Int]
actualwidths = ([(Int, Int, Int)] -> Int) -> [[(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, Int)] -> [Int]) -> [(Int, Int, Int)] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, Int, Int) -> Int) -> [(Int, Int, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Int, Int, Int) -> Int
forall {a} {b} {c}. (a, b, c) -> a
first3 ) ([[(Int, Int, Int)]] -> [Int]) -> [[(Int, Int, Int)]] -> [Int]
forall a b. (a -> b) -> a -> b
$ [[(Int, Int, Int)]]
cols
budgetwidths :: [Int]
budgetwidths = ([(Int, Int, Int)] -> Int) -> [[(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, Int)] -> [Int]) -> [(Int, Int, Int)] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, Int, Int) -> Int) -> [(Int, Int, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Int, Int, Int) -> Int
forall {a} {b} {c}. (a, b, c) -> b
second3) ([[(Int, Int, Int)]] -> [Int]) -> [[(Int, Int, Int)]] -> [Int]
forall a b. (a -> b) -> a -> b
$ [[(Int, Int, Int)]]
cols
percentwidths :: [Int]
percentwidths = ([(Int, Int, Int)] -> Int) -> [[(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, Int)] -> [Int]) -> [(Int, Int, Int)] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, Int, Int) -> Int) -> [(Int, Int, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Int, Int, Int) -> Int
forall {a} {b} {c}. (a, b, c) -> c
third3 ) ([[(Int, Int, Int)]] -> [Int]) -> [[(Int, Int, Int)]] -> [Int]
forall a b. (a -> b) -> a -> b
$ [[(Int, Int, Int)]]
cols
catcolumnwidths :: [[[a]]] -> [[a]]
catcolumnwidths = ([[a]] -> [[a]] -> [[a]]) -> [[a]] -> [[[a]]] -> [[a]]
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (([a] -> [a] -> [a]) -> [[a]] -> [[a]] -> [[a]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
(++)) ([[a]] -> [[[a]]] -> [[a]]) -> [[a]] -> [[[a]]] -> [[a]]
forall a b. (a -> b) -> a -> b
$ [a] -> [[a]]
forall a. a -> [a]
repeat []
cols :: [[(Int, Int, Int)]]
cols = [[(Int, Int, Int)]] -> [[(Int, Int, Int)]]
forall a. [[a]] -> [[a]]
maybetranspose ([[(Int, Int, Int)]] -> [[(Int, Int, Int)]])
-> [[(Int, Int, Int)]] -> [[(Int, Int, Int)]]
forall a b. (a -> b) -> a -> b
$ [[[(Int, Int, Int)]]] -> [[(Int, Int, Int)]]
forall {a}. [[[a]]] -> [[a]]
catcolumnwidths ([[[(Int, Int, Int)]]] -> [[(Int, Int, Int)]])
-> [[[(Int, Int, Int)]]] -> [[(Int, Int, Int)]]
forall a b. (a -> b) -> a -> b
$ (PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
-> [[(Int, Int, Int)]])
-> [PeriodicReportRow DisplayName (Maybe Change, Maybe Change)]
-> [[[(Int, Int, Int)]]]
forall a b. (a -> b) -> [a] -> [b]
map ([(Maybe Change, Maybe Change)] -> [[(Int, Int, Int)]]
cellswidth ([(Maybe Change, Maybe Change)] -> [[(Int, Int, Int)]])
-> (PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
-> [(Maybe Change, Maybe Change)])
-> PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
-> [[(Int, Int, Int)]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
-> [(Maybe Change, Maybe Change)]
forall a.
PeriodicReportRow a (Maybe Change, Maybe Change)
-> [(Maybe Change, Maybe Change)]
rowToBudgetCells) [PeriodicReportRow DisplayName (Maybe Change, Maybe Change)]
items [[[(Int, Int, Int)]]]
-> [[[(Int, Int, Int)]]] -> [[[(Int, Int, Int)]]]
forall a. [a] -> [a] -> [a]
++ [[(Maybe Change, Maybe Change)] -> [[(Int, Int, Int)]]
cellswidth ([(Maybe Change, Maybe Change)] -> [[(Int, Int, Int)]])
-> [(Maybe Change, Maybe Change)] -> [[(Int, Int, Int)]]
forall a b. (a -> b) -> a -> b
$ PeriodicReportRow () (Maybe Change, Maybe Change)
-> [(Maybe Change, Maybe Change)]
forall a.
PeriodicReportRow a (Maybe Change, Maybe Change)
-> [(Maybe Change, Maybe Change)]
rowToBudgetCells PeriodicReportRow () (Maybe Change, Maybe Change)
totrow]
cellswidth :: [BudgetCell] -> [[(Int, Int, Int)]]
cellswidth :: [(Maybe Change, Maybe Change)] -> [[(Int, Int, Int)]]
cellswidth [(Maybe Change, Maybe Change)]
row =
let cs :: [Text]
cs = [(Maybe Change, Maybe Change)] -> [Text]
budgetCellsCommodities [(Maybe Change, Maybe Change)]
row
(Change -> [WideBuilder]
showmixed, BudgetCalcPercentagesFn
percbudget) = [Text] -> (Change -> [WideBuilder], BudgetCalcPercentagesFn)
mkBudgetDisplayFns [Text]
cs
disp :: (Maybe Change, Maybe Change) -> [BudgetDisplayCell]
disp = (Change -> [WideBuilder])
-> BudgetCalcPercentagesFn
-> (Maybe Change, Maybe Change)
-> [BudgetDisplayCell]
showcell Change -> [WideBuilder]
showmixed BudgetCalcPercentagesFn
percbudget
budgetpercwidth :: (WideBuilder, Maybe WideBuilder) -> (Int, Int)
budgetpercwidth = WideBuilder -> Int
wbWidth (WideBuilder -> Int)
-> (Maybe WideBuilder -> Int)
-> (WideBuilder, Maybe WideBuilder)
-> (Int, Int)
forall b c b' c'. (b -> c) -> (b' -> c') -> (b, b') -> (c, c')
forall (a :: * -> * -> *) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
*** Int -> (WideBuilder -> Int) -> Maybe WideBuilder -> Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
0 WideBuilder -> Int
wbWidth
cellwidth :: BudgetDisplayCell -> (Int, Int, Int)
cellwidth (WideBuilder
am, Maybe (WideBuilder, Maybe WideBuilder)
bm) = let (Int
bw, Int
pw) = (Int, Int)
-> ((WideBuilder, Maybe WideBuilder) -> (Int, Int))
-> Maybe (WideBuilder, Maybe WideBuilder)
-> (Int, Int)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Int
0, Int
0) (WideBuilder, Maybe WideBuilder) -> (Int, Int)
budgetpercwidth Maybe (WideBuilder, Maybe WideBuilder)
bm in (WideBuilder -> Int
wbWidth WideBuilder
am, Int
bw, Int
pw)
in ((Maybe Change, Maybe Change) -> [(Int, Int, Int)])
-> [(Maybe Change, Maybe Change)] -> [[(Int, Int, Int)]]
forall a b. (a -> b) -> [a] -> [b]
map ((BudgetDisplayCell -> (Int, Int, Int))
-> [BudgetDisplayCell] -> [(Int, Int, Int)]
forall a b. (a -> b) -> [a] -> [b]
map BudgetDisplayCell -> (Int, Int, Int)
cellwidth ([BudgetDisplayCell] -> [(Int, Int, Int)])
-> ((Maybe Change, Maybe Change) -> [BudgetDisplayCell])
-> (Maybe Change, Maybe Change)
-> [(Int, Int, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Change, Maybe Change) -> [BudgetDisplayCell]
disp) [(Maybe Change, Maybe Change)]
row
totrowwidths :: [(Int, Int, Int)]
totrowwidths :: [(Int, Int, Int)]
totrowwidths
| Bool
transpose_ = Int -> [(Int, Int, Int)] -> [(Int, Int, Int)]
forall a. Int -> [a] -> [a]
drop ([[BudgetDisplayCell]] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[BudgetDisplayCell]]
texts) [(Int, Int, Int)]
widths
| Bool
otherwise = [(Int, Int, Int)]
widths
maybetranspose :: [[a]] -> [[a]]
maybetranspose
| Bool
transpose_ = [[a]] -> [[a]]
forall a. [[a]] -> [[a]]
transpose
| Bool
otherwise = [[a]] -> [[a]]
forall a. a -> a
id
([Text]
accts', [WideBuilder]
itemscs, [[BudgetDisplayCell]]
texts) = [(Text, WideBuilder, [BudgetDisplayCell])]
-> ([Text], [WideBuilder], [[BudgetDisplayCell]])
forall a b c. [(a, b, c)] -> ([a], [b], [c])
unzip3 ([(Text, WideBuilder, [BudgetDisplayCell])]
-> ([Text], [WideBuilder], [[BudgetDisplayCell]]))
-> [(Text, WideBuilder, [BudgetDisplayCell])]
-> ([Text], [WideBuilder], [[BudgetDisplayCell]])
forall a b. (a -> b) -> a -> b
$ [[(Text, WideBuilder, [BudgetDisplayCell])]]
-> [(Text, WideBuilder, [BudgetDisplayCell])]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[(Text, WideBuilder, [BudgetDisplayCell])]]
shownitems
where
shownitems :: [[(AccountName, WideBuilder, BudgetDisplayRow)]]
shownitems :: [[(Text, WideBuilder, [BudgetDisplayCell])]]
shownitems =
(PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
-> [(Text, WideBuilder, [BudgetDisplayCell])])
-> [PeriodicReportRow DisplayName (Maybe Change, Maybe Change)]
-> [[(Text, WideBuilder, [BudgetDisplayCell])]]
forall a b. (a -> b) -> [a] -> [b]
map (\PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
i ->
let
addacctcolumn :: [(b, c)] -> [(Text, b, c)]
addacctcolumn = ((b, c) -> (Text, b, c)) -> [(b, c)] -> [(Text, b, c)]
forall a b. (a -> b) -> [a] -> [b]
map (\(b
cs, c
cvals) -> (PeriodicReportRow DisplayName (Maybe Change, Maybe Change) -> Text
forall {a}. PeriodicReportRow DisplayName a -> Text
renderacct PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
i, b
cs, c
cvals))
isunbudgetedrow :: Bool
isunbudgetedrow = DisplayName -> Text
displayFull (PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
-> DisplayName
forall a b. PeriodicReportRow a b -> a
prrName PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
i) Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
unbudgetedAccountName
in [(WideBuilder, [BudgetDisplayCell])]
-> [(Text, WideBuilder, [BudgetDisplayCell])]
forall {b} {c}. [(b, c)] -> [(Text, b, c)]
addacctcolumn ([(WideBuilder, [BudgetDisplayCell])]
-> [(Text, WideBuilder, [BudgetDisplayCell])])
-> [(WideBuilder, [BudgetDisplayCell])]
-> [(Text, WideBuilder, [BudgetDisplayCell])]
forall a b. (a -> b) -> a -> b
$ Bool
-> [(Maybe Change, Maybe Change)]
-> [(WideBuilder, [BudgetDisplayCell])]
showrow Bool
isunbudgetedrow ([(Maybe Change, Maybe Change)]
-> [(WideBuilder, [BudgetDisplayCell])])
-> [(Maybe Change, Maybe Change)]
-> [(WideBuilder, [BudgetDisplayCell])]
forall a b. (a -> b) -> a -> b
$ PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
-> [(Maybe Change, Maybe Change)]
forall a.
PeriodicReportRow a (Maybe Change, Maybe Change)
-> [(Maybe Change, Maybe Change)]
rowToBudgetCells PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
i)
[PeriodicReportRow DisplayName (Maybe Change, Maybe Change)]
items
where
renderacct :: PeriodicReportRow DisplayName a -> Text
renderacct PeriodicReportRow DisplayName a
row = case AccountListMode
accountlistmode_ of
AccountListMode
ALTree -> 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
AccountListMode
ALFlat -> Int -> Text -> Text
accountNameDrop (Int
drop_) (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ PeriodicReportRow DisplayName a -> Text
forall {a}. PeriodicReportRow DisplayName a -> Text
prrFullName PeriodicReportRow DisplayName a
row
([WideBuilder]
totrowcs, [[BudgetDisplayCell]]
totrowtexts) = [(WideBuilder, [BudgetDisplayCell])]
-> ([WideBuilder], [[BudgetDisplayCell]])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(WideBuilder, [BudgetDisplayCell])]
-> ([WideBuilder], [[BudgetDisplayCell]]))
-> [(WideBuilder, [BudgetDisplayCell])]
-> ([WideBuilder], [[BudgetDisplayCell]])
forall a b. (a -> b) -> a -> b
$ [[(WideBuilder, [BudgetDisplayCell])]]
-> [(WideBuilder, [BudgetDisplayCell])]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[(WideBuilder, [BudgetDisplayCell])]]
showntotrow
where
showntotrow :: [[(WideBuilder, BudgetDisplayRow)]]
showntotrow :: [[(WideBuilder, [BudgetDisplayCell])]]
showntotrow = [Bool
-> [(Maybe Change, Maybe Change)]
-> [(WideBuilder, [BudgetDisplayCell])]
showrow Bool
False ([(Maybe Change, Maybe Change)]
-> [(WideBuilder, [BudgetDisplayCell])])
-> [(Maybe Change, Maybe Change)]
-> [(WideBuilder, [BudgetDisplayCell])]
forall a b. (a -> b) -> a -> b
$ PeriodicReportRow () (Maybe Change, Maybe Change)
-> [(Maybe Change, Maybe Change)]
forall a.
PeriodicReportRow a (Maybe Change, Maybe Change)
-> [(Maybe Change, Maybe Change)]
rowToBudgetCells PeriodicReportRow () (Maybe Change, Maybe Change)
totrow]
rowToBudgetCells :: PeriodicReportRow a BudgetCell -> [BudgetCell]
rowToBudgetCells :: forall a.
PeriodicReportRow a (Maybe Change, Maybe Change)
-> [(Maybe Change, Maybe Change)]
rowToBudgetCells (PeriodicReportRow a
_ [(Maybe Change, Maybe Change)]
as (Maybe Change, Maybe Change)
rowtot (Maybe Change, Maybe Change)
rowavg) = [(Maybe Change, Maybe Change)]
as
[(Maybe Change, Maybe Change)]
-> [(Maybe Change, Maybe Change)] -> [(Maybe Change, Maybe Change)]
forall a. [a] -> [a] -> [a]
++ [(Maybe Change, Maybe Change)
rowtot | Bool
row_total_ Bool -> Bool -> Bool
&& Bool -> Bool
not ([(Maybe Change, Maybe Change)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Maybe Change, Maybe Change)]
as)]
[(Maybe Change, Maybe Change)]
-> [(Maybe Change, Maybe Change)] -> [(Maybe Change, Maybe Change)]
forall a. [a] -> [a] -> [a]
++ [(Maybe Change, Maybe Change)
rowavg | Bool
average_ Bool -> Bool -> Bool
&& Bool -> Bool
not ([(Maybe Change, Maybe Change)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Maybe Change, Maybe Change)]
as)]
showrow :: Bool -> [BudgetCell] -> [(WideBuilder, BudgetDisplayRow)]
showrow :: Bool
-> [(Maybe Change, Maybe Change)]
-> [(WideBuilder, [BudgetDisplayCell])]
showrow Bool
isunbudgetedrow [(Maybe Change, Maybe Change)]
cells =
let
cs :: [Text]
cs = [(Maybe Change, Maybe Change)] -> [Text]
budgetCellsCommodities [(Maybe Change, Maybe Change)]
cells
cs1 :: [Text]
cs1 = if [Text] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Text]
cs Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
isunbudgetedrow then [Text
""] else [Text]
cs
(Change -> [WideBuilder]
showmixed, BudgetCalcPercentagesFn
percbudget) = [Text] -> (Change -> [WideBuilder], BudgetCalcPercentagesFn)
mkBudgetDisplayFns [Text]
cs1
in
[WideBuilder]
-> [[BudgetDisplayCell]] -> [(WideBuilder, [BudgetDisplayCell])]
forall a b. [a] -> [b] -> [(a, b)]
zip ((Text -> WideBuilder) -> [Text] -> [WideBuilder]
forall a b. (a -> b) -> [a] -> [b]
map Text -> WideBuilder
wbFromText [Text]
cs1) ([[BudgetDisplayCell]] -> [(WideBuilder, [BudgetDisplayCell])])
-> [[BudgetDisplayCell]] -> [(WideBuilder, [BudgetDisplayCell])]
forall a b. (a -> b) -> a -> b
$
[[BudgetDisplayCell]] -> [[BudgetDisplayCell]]
forall a. [[a]] -> [[a]]
transpose ([[BudgetDisplayCell]] -> [[BudgetDisplayCell]])
-> [[BudgetDisplayCell]] -> [[BudgetDisplayCell]]
forall a b. (a -> b) -> a -> b
$
((Maybe Change, Maybe Change) -> [BudgetDisplayCell])
-> [(Maybe Change, Maybe Change)] -> [[BudgetDisplayCell]]
forall a b. (a -> b) -> [a] -> [b]
map ((Change -> [WideBuilder])
-> BudgetCalcPercentagesFn
-> (Maybe Change, Maybe Change)
-> [BudgetDisplayCell]
showcell Change -> [WideBuilder]
showmixed BudgetCalcPercentagesFn
percbudget)
[(Maybe Change, Maybe Change)]
cells
budgetCellsCommodities :: [BudgetCell] -> [CommoditySymbol]
budgetCellsCommodities :: [(Maybe Change, Maybe Change)] -> [Text]
budgetCellsCommodities = Set Text -> [Text]
forall a. Set a -> [a]
S.toList (Set Text -> [Text])
-> ([(Maybe Change, Maybe Change)] -> Set Text)
-> [(Maybe Change, Maybe Change)]
-> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Set Text -> Set Text -> Set Text)
-> Set Text -> [Set Text] -> Set Text
forall b a. (b -> a -> b) -> b -> [a] -> b
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] -> Set Text)
-> ([(Maybe Change, Maybe Change)] -> [Set Text])
-> [(Maybe Change, Maybe Change)]
-> Set Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Maybe Change, Maybe Change) -> Set Text)
-> [(Maybe Change, Maybe Change)] -> [Set Text]
forall a b. (a -> b) -> [a] -> [b]
map (Maybe Change, Maybe Change) -> Set Text
budgetCellCommodities
where
budgetCellCommodities :: BudgetCell -> S.Set CommoditySymbol
budgetCellCommodities :: (Maybe Change, Maybe Change) -> Set Text
budgetCellCommodities (Maybe Change
am, Maybe Change
bm) = Maybe Change -> Set Text
f Maybe Change
am Set Text -> Set Text -> Set Text
forall a. Ord a => Set a -> Set a -> Set a
`S.union` Maybe Change -> Set Text
f Maybe Change
bm
where f :: Maybe Change -> Set Text
f = Set Text -> (Change -> Set Text) -> Maybe Change -> Set Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Set Text
forall a. Monoid a => a
mempty Change -> Set Text
maCommodities
showcell :: BudgetShowAmountsFn -> BudgetCalcPercentagesFn -> BudgetCell -> BudgetDisplayRow
showcell :: (Change -> [WideBuilder])
-> BudgetCalcPercentagesFn
-> (Maybe Change, Maybe Change)
-> [BudgetDisplayCell]
showcell Change -> [WideBuilder]
showCommodityAmounts BudgetCalcPercentagesFn
calcCommodityPercentages (Maybe Change
mactual, Maybe Change
mbudget) =
[WideBuilder]
-> [Maybe (WideBuilder, Maybe WideBuilder)] -> [BudgetDisplayCell]
forall a b. [a] -> [b] -> [(a, b)]
zip [WideBuilder]
actualamts [Maybe (WideBuilder, Maybe WideBuilder)]
budgetinfos
where
actual :: Change
actual = Change -> Maybe Change -> Change
forall a. a -> Maybe a -> a
fromMaybe Change
nullmixedamt Maybe Change
mactual
actualamts :: [WideBuilder]
actualamts = Change -> [WideBuilder]
showCommodityAmounts Change
actual
budgetinfos :: [Maybe (WideBuilder, Maybe WideBuilder)]
budgetinfos =
case Maybe Change
mbudget of
Maybe Change
Nothing -> Maybe (WideBuilder, Maybe WideBuilder)
-> [Maybe (WideBuilder, Maybe WideBuilder)]
forall a. a -> [a]
repeat Maybe (WideBuilder, Maybe WideBuilder)
forall a. Maybe a
Nothing
Just Change
goal -> ((WideBuilder, Maybe WideBuilder)
-> Maybe (WideBuilder, Maybe WideBuilder))
-> [(WideBuilder, Maybe WideBuilder)]
-> [Maybe (WideBuilder, Maybe WideBuilder)]
forall a b. (a -> b) -> [a] -> [b]
map (WideBuilder, Maybe WideBuilder)
-> Maybe (WideBuilder, Maybe WideBuilder)
forall a. a -> Maybe a
Just ([(WideBuilder, Maybe WideBuilder)]
-> [Maybe (WideBuilder, Maybe WideBuilder)])
-> [(WideBuilder, Maybe WideBuilder)]
-> [Maybe (WideBuilder, Maybe WideBuilder)]
forall a b. (a -> b) -> a -> b
$ Change -> [(WideBuilder, Maybe WideBuilder)]
showGoalAmountsAndPercentages Change
goal
where
showGoalAmountsAndPercentages :: MixedAmount -> [(WideBuilder, Maybe WideBuilder)]
showGoalAmountsAndPercentages :: Change -> [(WideBuilder, Maybe WideBuilder)]
showGoalAmountsAndPercentages Change
goal = [WideBuilder]
-> [Maybe WideBuilder] -> [(WideBuilder, Maybe WideBuilder)]
forall a b. [a] -> [b] -> [(a, b)]
zip [WideBuilder]
amts [Maybe WideBuilder]
mpcts
where
amts :: [WideBuilder]
amts = Change -> [WideBuilder]
showCommodityAmounts Change
goal
mpcts :: [Maybe WideBuilder]
mpcts = (Maybe Percentage -> Maybe WideBuilder)
-> [Maybe Percentage] -> [Maybe WideBuilder]
forall a b. (a -> b) -> [a] -> [b]
map (Percentage -> WideBuilder
showrounded (Percentage -> WideBuilder)
-> Maybe Percentage -> Maybe WideBuilder
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) ([Maybe Percentage] -> [Maybe WideBuilder])
-> [Maybe Percentage] -> [Maybe WideBuilder]
forall a b. (a -> b) -> a -> b
$ BudgetCalcPercentagesFn
calcCommodityPercentages Change
actual Change
goal
where showrounded :: Percentage -> WideBuilder
showrounded = Text -> WideBuilder
wbFromText (Text -> WideBuilder)
-> (Percentage -> Text) -> Percentage -> WideBuilder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CommandHelpStr -> Text
T.pack (CommandHelpStr -> Text)
-> (Percentage -> CommandHelpStr) -> Percentage -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Percentage -> CommandHelpStr
forall a. Show a => a -> CommandHelpStr
show (Percentage -> CommandHelpStr)
-> (Percentage -> Percentage) -> Percentage -> CommandHelpStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Percentage -> Percentage
forall i. Integral i => Word8 -> DecimalRaw i -> DecimalRaw i
roundTo Word8
0
mkBudgetDisplayFns :: [CommoditySymbol] -> (BudgetShowAmountsFn, BudgetCalcPercentagesFn)
mkBudgetDisplayFns :: [Text] -> (Change -> [WideBuilder], BudgetCalcPercentagesFn)
mkBudgetDisplayFns [Text]
cs = case Layout
layout_ of
LayoutWide Maybe Int
width ->
( WideBuilder -> [WideBuilder]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (WideBuilder -> [WideBuilder])
-> (Change -> WideBuilder) -> Change -> [WideBuilder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AmountFormat -> Change -> WideBuilder
showMixedAmountB AmountFormat
oneLineNoCostFmt{displayMaxWidth=width, displayColour=color_}
, \Change
a -> Maybe Percentage -> [Maybe Percentage]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Percentage -> [Maybe Percentage])
-> (Change -> Maybe Percentage) -> Change -> [Maybe Percentage]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Change -> Change -> Maybe Percentage
percentage Change
a)
Layout
_ -> ( AmountFormat -> Change -> [WideBuilder]
showMixedAmountLinesB AmountFormat
noCostFmt{displayCommodity=layout_/=LayoutBare, displayCommodityOrder=Just cs, displayMinWidth=Nothing, displayColour=color_}
, \Change
a Change
b -> (Text -> Maybe Percentage) -> [Text] -> [Maybe Percentage]
forall a b. (a -> b) -> [a] -> [b]
map (Change -> Change -> Text -> Maybe Percentage
percentage' Change
a Change
b) [Text]
cs)
where
percentage :: Change -> BudgetGoal -> Maybe Percentage
percentage :: Change -> Change -> Maybe Percentage
percentage Change
actual Change
budget =
case (Change -> [Amount]
costedAmounts Change
actual, Change -> [Amount]
costedAmounts Change
budget) of
([Amount
a], [Amount
b]) | (Amount -> Text
acommodity Amount
a Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Amount -> Text
acommodity Amount
b Bool -> Bool -> Bool
|| Amount -> Bool
amountLooksZero Amount
a) Bool -> Bool -> Bool
&& Bool -> Bool
not (Amount -> Bool
amountLooksZero Amount
b)
-> Percentage -> Maybe Percentage
forall a. a -> Maybe a
Just (Percentage -> Maybe Percentage) -> Percentage -> Maybe Percentage
forall a b. (a -> b) -> a -> b
$ Percentage
100 Percentage -> Percentage -> Percentage
forall a. Num a => a -> a -> a
* Amount -> Percentage
aquantity Amount
a Percentage -> Percentage -> Percentage
forall a. Fractional a => a -> a -> a
/ Amount -> Percentage
aquantity Amount
b
([Amount], [Amount])
_ -> Maybe Percentage
forall a. Maybe a
Nothing
where
costedAmounts :: Change -> [Amount]
costedAmounts = case Maybe ConversionOp
conversionop_ of
Just ConversionOp
ToCost -> Change -> [Amount]
amounts (Change -> [Amount]) -> (Change -> Change) -> Change -> [Amount]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Change -> Change
mixedAmountCost
Maybe ConversionOp
_ -> Change -> [Amount]
amounts
percentage' :: Change -> BudgetGoal -> CommoditySymbol -> Maybe Percentage
percentage' :: Change -> Change -> Text -> Maybe Percentage
percentage' Change
am Change
bm Text
c = case ((,) (Maybe Amount -> Maybe Amount -> (Maybe Amount, Maybe Amount))
-> (Change -> Maybe Amount)
-> Change
-> Change
-> (Maybe Amount, Maybe Amount)
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (Amount -> Bool) -> [Amount] -> Maybe Amount
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
(==) Text
c (Text -> Bool) -> (Amount -> Text) -> Amount -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Amount -> Text
acommodity) ([Amount] -> Maybe Amount)
-> (Change -> [Amount]) -> Change -> Maybe Amount
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Change -> [Amount]
amounts) Change
am Change
bm of
(Just Amount
a, Just Amount
b) -> Change -> Change -> Maybe Percentage
percentage (Amount -> Change
mixedAmount Amount
a) (Amount -> Change
mixedAmount Amount
b)
(Maybe Amount, Maybe Amount)
_ -> Maybe Percentage
forall a. Maybe a
Nothing
budgetReportAsCsv :: ReportOpts -> BudgetReport -> [[Text]]
budgetReportAsCsv :: ReportOpts -> BudgetReport -> CSV
budgetReportAsCsv ReportOpts
ropts BudgetReport
report
= ([Cell Text] -> [Text]) -> [[Cell Text]] -> CSV
forall a b. (a -> b) -> [a] -> [b]
map ((Cell Text -> Text) -> [Cell Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Cell Text -> Text
forall text. Cell text -> text
Ods.cellContent) ([[Cell Text]] -> CSV) -> [[Cell Text]] -> CSV
forall a b. (a -> b) -> a -> b
$
ReportOpts -> BudgetReport -> [[Cell Text]]
budgetReportAsSpreadsheet ReportOpts
ropts BudgetReport
report
budgetReportAsSpreadsheet :: ReportOpts -> BudgetReport -> [[Ods.Cell Text]]
budgetReportAsSpreadsheet :: ReportOpts -> BudgetReport -> [[Cell Text]]
budgetReportAsSpreadsheet
ReportOpts{Bool
Int
[Text]
[Status]
SortSpec
Maybe Int
Maybe Text
Maybe NormalSign
Maybe ConversionOp
Maybe ValuationType
StringFormat
Interval
Period
AccountListMode
BalanceAccumulation
BalanceCalculation
Layout
accountlistmode_ :: ReportOpts -> AccountListMode
average_ :: ReportOpts -> Bool
balanceaccum_ :: ReportOpts -> BalanceAccumulation
balancecalc_ :: ReportOpts -> BalanceCalculation
budgetpat_ :: ReportOpts -> Maybe Text
color_ :: ReportOpts -> Bool
conversionop_ :: ReportOpts -> Maybe ConversionOp
date2_ :: ReportOpts -> Bool
declared_ :: ReportOpts -> Bool
depth_ :: ReportOpts -> Maybe Int
drop_ :: ReportOpts -> Int
empty_ :: ReportOpts -> Bool
format_ :: ReportOpts -> StringFormat
infer_prices_ :: ReportOpts -> Bool
interval_ :: ReportOpts -> Interval
invert_ :: ReportOpts -> Bool
layout_ :: ReportOpts -> Layout
no_elide_ :: ReportOpts -> Bool
no_total_ :: ReportOpts -> Bool
normalbalance_ :: ReportOpts -> Maybe NormalSign
percent_ :: ReportOpts -> Bool
period_ :: ReportOpts -> Period
pretty_ :: ReportOpts -> Bool
querystring_ :: ReportOpts -> [Text]
real_ :: ReportOpts -> Bool
related_ :: ReportOpts -> Bool
row_total_ :: ReportOpts -> Bool
show_costs_ :: ReportOpts -> Bool
sort_amount_ :: ReportOpts -> Bool
sortspec_ :: ReportOpts -> SortSpec
statuses_ :: ReportOpts -> [Status]
summary_only_ :: ReportOpts -> Bool
transpose_ :: ReportOpts -> Bool
txn_dates_ :: ReportOpts -> Bool
value_ :: ReportOpts -> Maybe ValuationType
period_ :: Period
interval_ :: Interval
statuses_ :: [Status]
conversionop_ :: Maybe ConversionOp
value_ :: Maybe ValuationType
infer_prices_ :: Bool
depth_ :: Maybe Int
date2_ :: Bool
empty_ :: Bool
no_elide_ :: Bool
real_ :: Bool
format_ :: StringFormat
pretty_ :: Bool
querystring_ :: [Text]
average_ :: Bool
related_ :: Bool
sortspec_ :: SortSpec
txn_dates_ :: Bool
balancecalc_ :: BalanceCalculation
balanceaccum_ :: BalanceAccumulation
budgetpat_ :: Maybe Text
accountlistmode_ :: AccountListMode
drop_ :: Int
declared_ :: Bool
row_total_ :: Bool
no_total_ :: Bool
summary_only_ :: Bool
show_costs_ :: Bool
sort_amount_ :: Bool
percent_ :: Bool
invert_ :: Bool
normalbalance_ :: Maybe NormalSign
color_ :: Bool
transpose_ :: Bool
layout_ :: Layout
..}
(PeriodicReport [DateSpan]
colspans [PeriodicReportRow DisplayName (Maybe Change, Maybe Change)]
items PeriodicReportRow () (Maybe Change, Maybe Change)
totrow)
= (if Bool
transpose_ then [[Cell Text]] -> [[Cell Text]]
forall a. [[a]] -> [[a]]
transpose else [[Cell Text]] -> [[Cell Text]]
forall a. a -> a
id) ([[Cell Text]] -> [[Cell Text]]) -> [[Cell Text]] -> [[Cell Text]]
forall a b. (a -> b) -> a -> b
$
((Text -> Cell Text) -> [Text] -> [Cell Text]
forall a b. (a -> b) -> [a] -> [b]
map (\Text
content -> (Text -> Cell Text
forall text. text -> Cell text
cell Text
content) {Ods.cellStyle = Ods.Head}) ([Text] -> [Cell Text]) -> [Text] -> [Cell Text]
forall a b. (a -> b) -> a -> b
$
Text
"Account" Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:
[Text
"Commodity" | Layout
layout_ Layout -> Layout -> Bool
forall a. Eq a => a -> a -> Bool
== Layout
LayoutBare ]
[Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ (DateSpan -> [Text]) -> [DateSpan] -> [Text]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\DateSpan
spn -> [DateSpan -> Text
showDateSpan DateSpan
spn, Text
"budget"]) [DateSpan]
colspans
[Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ CSV -> [Text]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Text
"Total" ,Text
"budget"] | Bool
row_total_]
[Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ CSV -> [Text]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Text
"Average",Text
"budget"] | Bool
average_]
) [Cell Text] -> [[Cell Text]] -> [[Cell Text]]
forall a. a -> [a] -> [a]
:
(PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
-> [[Cell Text]])
-> [PeriodicReportRow DisplayName (Maybe Change, Maybe Change)]
-> [[Cell Text]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ((PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
-> Text)
-> PeriodicReportRow DisplayName (Maybe Change, Maybe Change)
-> [[Cell Text]]
forall a.
(PeriodicReportRow a (Maybe Change, Maybe Change) -> Text)
-> PeriodicReportRow a (Maybe Change, Maybe Change)
-> [[Cell Text]]
rowAsTexts PeriodicReportRow DisplayName (Maybe Change, Maybe Change) -> Text
forall {a}. PeriodicReportRow DisplayName a -> Text
prrFullName) [PeriodicReportRow DisplayName (Maybe Change, Maybe Change)]
items
[[Cell Text]] -> [[Cell Text]] -> [[Cell Text]]
forall a. [a] -> [a] -> [a]
++ ([Cell Text] -> [Cell Text]) -> [[Cell Text]] -> [[Cell Text]]
forall a b. (a -> b) -> [a] -> [b]
map ((Cell Text -> Cell Text) -> [Cell Text] -> [Cell Text]
forall a b. (a -> b) -> [a] -> [b]
map (\Cell Text
c -> Cell Text
c {Ods.cellStyle = Ods.Body Ods.Total}))
([[[Cell Text]]] -> [[Cell Text]]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ (PeriodicReportRow () (Maybe Change, Maybe Change) -> Text)
-> PeriodicReportRow () (Maybe Change, Maybe Change)
-> [[Cell Text]]
forall a.
(PeriodicReportRow a (Maybe Change, Maybe Change) -> Text)
-> PeriodicReportRow a (Maybe Change, Maybe Change)
-> [[Cell Text]]
rowAsTexts (Text -> PeriodicReportRow () (Maybe Change, Maybe Change) -> Text
forall a b. a -> b -> a
const Text
totalRowHeadingBudgetCsv) PeriodicReportRow () (Maybe Change, Maybe Change)
totrow | Bool -> Bool
not Bool
no_total_ ])
where
cell :: text -> Cell text
cell = text -> Cell text
forall text. text -> Cell text
Ods.defaultCell
flattentuples :: [(a, a)] -> [a]
flattentuples [(a, a)]
tups = [[a]] -> [a]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[a
a,a
b] | (a
a,a
b) <- [(a, a)]
tups]
showNorm :: Maybe Change -> Cell Text
showNorm = Cell Text -> (Change -> Cell Text) -> Maybe Change -> Cell Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Cell Text
forall text. Monoid text => Cell text
Ods.emptyCell ((WideBuilder -> Text) -> Cell WideBuilder -> Cell Text
forall a b. (a -> b) -> Cell a -> Cell b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap WideBuilder -> Text
wbToText (Cell WideBuilder -> Cell Text)
-> (Change -> Cell WideBuilder) -> Change -> Cell Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AmountFormat -> Change -> Cell WideBuilder
cellFromMixedAmount AmountFormat
oneLineNoCostFmt)
rowAsTexts :: (PeriodicReportRow a BudgetCell -> Text)
-> PeriodicReportRow a BudgetCell
-> [[Ods.Cell Text]]
rowAsTexts :: forall a.
(PeriodicReportRow a (Maybe Change, Maybe Change) -> Text)
-> PeriodicReportRow a (Maybe Change, Maybe Change)
-> [[Cell Text]]
rowAsTexts PeriodicReportRow a (Maybe Change, Maybe Change) -> Text
render row :: PeriodicReportRow a (Maybe Change, Maybe Change)
row@(PeriodicReportRow a
_ [(Maybe Change, Maybe Change)]
as (Maybe Change
rowtot,Maybe Change
budgettot) (Maybe Change
rowavg, Maybe Change
budgetavg))
| Layout
layout_ Layout -> Layout -> Bool
forall a. Eq a => a -> a -> Bool
/= Layout
LayoutBare = [Text -> Cell Text
forall text. text -> Cell text
cell (PeriodicReportRow a (Maybe Change, Maybe Change) -> Text
render PeriodicReportRow a (Maybe Change, Maybe Change)
row) Cell Text -> [Cell Text] -> [Cell Text]
forall a. a -> [a] -> [a]
: (Maybe Change -> Cell Text) -> [Maybe Change] -> [Cell Text]
forall a b. (a -> b) -> [a] -> [b]
map Maybe Change -> Cell Text
showNorm [Maybe Change]
vals]
| Bool
otherwise =
[[Cell Text]] -> [[Cell Text]]
joinNames ([[Cell Text]] -> [[Cell Text]])
-> ([Maybe Change] -> [[Cell Text]])
-> [Maybe Change]
-> [[Cell Text]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cell Text -> [Cell Text] -> [Cell Text])
-> [Cell Text] -> [[Cell Text]] -> [[Cell Text]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (:) ((Text -> Cell Text) -> [Text] -> [Cell Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Cell Text
forall text. text -> Cell text
cell [Text]
cs)
([[Cell Text]] -> [[Cell Text]])
-> ([Maybe Change] -> [[Cell Text]])
-> [Maybe Change]
-> [[Cell Text]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Cell Text]] -> [[Cell Text]]
forall a. [[a]] -> [[a]]
transpose
([[Cell Text]] -> [[Cell Text]])
-> ([Maybe Change] -> [[Cell Text]])
-> [Maybe Change]
-> [[Cell Text]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Change -> [Cell Text]) -> [Maybe Change] -> [[Cell Text]]
forall a b. (a -> b) -> [a] -> [b]
map ((Cell WideBuilder -> Cell Text)
-> [Cell WideBuilder] -> [Cell Text]
forall a b. (a -> b) -> [a] -> [b]
map ((WideBuilder -> Text) -> Cell WideBuilder -> Cell Text
forall a b. (a -> b) -> Cell a -> Cell b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap WideBuilder -> Text
wbToText) ([Cell WideBuilder] -> [Cell Text])
-> (Maybe Change -> [Cell WideBuilder])
-> Maybe Change
-> [Cell Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AmountFormat -> Change -> [Cell WideBuilder]
cellsFromMixedAmount AmountFormat
dopts (Change -> [Cell WideBuilder])
-> (Maybe Change -> Change) -> Maybe Change -> [Cell WideBuilder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Change -> Maybe Change -> Change
forall a. a -> Maybe a -> a
fromMaybe Change
nullmixedamt)
([Maybe Change] -> [[Cell Text]])
-> [Maybe Change] -> [[Cell Text]]
forall a b. (a -> b) -> a -> b
$ [Maybe Change]
vals
where
cs :: [Text]
cs = Set Text -> [Text]
forall a. Set a -> [a]
S.toList (Set Text -> [Text])
-> ([Change] -> Set Text) -> [Change] -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Set Text] -> Set Text
forall a. Monoid a => [a] -> a
mconcat ([Set Text] -> Set Text)
-> ([Change] -> [Set Text]) -> [Change] -> Set Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Change -> Set Text) -> [Change] -> [Set Text]
forall a b. (a -> b) -> [a] -> [b]
map Change -> Set Text
maCommodities ([Change] -> [Text]) -> [Change] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Maybe Change] -> [Change]
forall a. [Maybe a] -> [a]
catMaybes [Maybe Change]
vals
dopts :: AmountFormat
dopts = AmountFormat
oneLineNoCostFmt{displayCommodity=layout_ /= LayoutBare, displayCommodityOrder=Just cs, displayMinWidth=Nothing}
vals :: [Maybe Change]
vals = [(Maybe Change, Maybe Change)] -> [Maybe Change]
forall {a}. [(a, a)] -> [a]
flattentuples [(Maybe Change, Maybe Change)]
as
[Maybe Change] -> [Maybe Change] -> [Maybe Change]
forall a. [a] -> [a] -> [a]
++ [[Maybe Change]] -> [Maybe Change]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Maybe Change
rowtot, Maybe Change
budgettot] | Bool
row_total_]
[Maybe Change] -> [Maybe Change] -> [Maybe Change]
forall a. [a] -> [a] -> [a]
++ [[Maybe Change]] -> [Maybe Change]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Maybe Change
rowavg, Maybe Change
budgetavg] | Bool
average_]
joinNames :: [[Cell Text]] -> [[Cell Text]]
joinNames = ([Cell Text] -> [Cell Text]) -> [[Cell Text]] -> [[Cell Text]]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> Cell Text
forall text. text -> Cell text
cell (PeriodicReportRow a (Maybe Change, Maybe Change) -> Text
render PeriodicReportRow a (Maybe Change, Maybe Change)
row) Cell Text -> [Cell Text] -> [Cell Text]
forall a. a -> [a] -> [a]
:)
tests_Balance :: TestTree
tests_Balance = CommandHelpStr -> [TestTree] -> TestTree
testGroup CommandHelpStr
"Balance" [
CommandHelpStr -> [TestTree] -> TestTree
testGroup CommandHelpStr
"balanceReportAsText" [
CommandHelpStr -> IO () -> TestTree
testCase CommandHelpStr
"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=defreportopts{no_total_=True}}
Builder -> Text
TB.toLazyText (ReportOpts -> BalanceReport -> Builder
balanceReportAsText (ReportSpec -> ReportOpts
_rsReportOpts ReportSpec
rspec) (ReportSpec -> Journal -> BalanceReport
balanceReport ReportSpec
rspec{_rsDay=fromGregorian 2008 11 26} Journal
j))
Text -> Text -> IO ()
forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
@?=
[Text] -> Text
TL.unlines
[Text
" -100 актив:наличные"
,Text
" 100 расходы:покупки"
]
]
]