    {- |
    New common report types, used by the BudgetReport for now, perhaps all reports later.
    -}
    {-# LANGUAGE DeriveAnyClass #-}
    {-# LANGUAGE DeriveFunctor  #-}
    {-# LANGUAGE DeriveGeneric  #-}

    module Hledger.Reports.ReportTypes
    ( PeriodicReport(..)
    , PeriodicReportRow(..)

    , Percentage
    , Change
    , Balance
    , Total
    , Average

    , periodicReportSpan
    , prMapName
    , prMapMaybeName

    , CompoundPeriodicReport(..)
    , CBCSubreportSpec(..)

    , DisplayName(..)
    , flatDisplayName
    , treeDisplayName

    , prrFullName
    , prrDisplayName
    , prrDepth
    , prrAdd
    ) where

    import Data.Aeson (ToJSON(..))
    import Data.Bifunctor (Bifunctor(..))
    import Data.Decimal (Decimal)
    import Data.Maybe (mapMaybe)
    import Data.Text (Text)
    import GHC.Generics (Generic)

    import Hledger.Data
    import Hledger.Query (Query)
    import Hledger.Reports.ReportOptions (ReportOpts)

    type Percentage = Decimal

    type Change  = MixedAmount  -- ^ A change in balance during a certain period.
    type Balance = MixedAmount  -- ^ An ending balance as of some date.
    type Total   = MixedAmount  -- ^ The sum of 'Change's in a report or a report row. Does not make sense for 'Balance's.
    type Average = MixedAmount  -- ^ The average of 'Change's or 'Balance's in a report or report row.

    -- | A periodic report is a generic tabular report, where each row corresponds
    -- to some label (usually an account name) and each column to a date period.
    -- The column periods are usually consecutive subperiods formed by splitting
    -- the overall report period by some report interval (daily, weekly, etc.).
    -- It has:
    --
    -- 1. a list of each column's period (date span)
    --
    -- 2. a list of rows, each containing:
    --
    --   * an account label
    --
    --   * the account's depth
    --
    --   * A list of amounts, one for each column. Depending on the value type,
    --     these can represent balance changes, ending balances, budget
    --     performance, etc. (for example, see 'BalanceAccumulation' and
    --     "Hledger.Cli.Commands.Balance").
    --
    --   * the total of the row's amounts for a periodic report,
    --     or zero for cumulative/historical reports (since summing
    --     end balances generally doesn't make sense).
    --
    --   * the average of the row's amounts
    --
    -- 3. the column totals, and the overall grand total (or zero for
    -- cumulative/historical reports) and grand average.

    data PeriodicReport a b =
      PeriodicReport
      { forall a b. PeriodicReport a b -> [DateSpan]
    prDates  :: [DateSpan]               -- The subperiods formed by splitting the overall
                                             -- report period by the report interval. For
                                             -- ending-balance reports, only the end date is
                                             -- significant. Usually displayed as report columns.
      , forall a b. PeriodicReport a b -> [PeriodicReportRow a b]
    prRows   :: [PeriodicReportRow a b]  -- One row per account in the report.
      , forall a b. PeriodicReport a b -> PeriodicReportRow () b
    prTotals :: PeriodicReportRow () b   -- The grand totals row.
      } deriving (Int -> PeriodicReport a b -> ShowS
    [PeriodicReport a b] -> ShowS
    PeriodicReport a b -> String
    (Int -> PeriodicReport a b -> ShowS)
    -> (PeriodicReport a b -> String)
    -> ([PeriodicReport a b] -> ShowS)
    -> Show (PeriodicReport a b)
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    forall a b. (Show a, Show b) => Int -> PeriodicReport a b -> ShowS
    forall a b. (Show a, Show b) => [PeriodicReport a b] -> ShowS
    forall a b. (Show a, Show b) => PeriodicReport a b -> String
    $cshowsPrec :: forall a b. (Show a, Show b) => Int -> PeriodicReport a b -> ShowS
    showsPrec :: Int -> PeriodicReport a b -> ShowS
    $cshow :: forall a b. (Show a, Show b) => PeriodicReport a b -> String
    show :: PeriodicReport a b -> String
    $cshowList :: forall a b. (Show a, Show b) => [PeriodicReport a b] -> ShowS
    showList :: [PeriodicReport a b] -> ShowS
    Show, (forall a b. (a -> b) -> PeriodicReport a a -> PeriodicReport a b)
    -> (forall a b. a -> PeriodicReport a b -> PeriodicReport a a)
    -> Functor (PeriodicReport a)
    forall a b. a -> PeriodicReport a b -> PeriodicReport a a
    forall a b. (a -> b) -> PeriodicReport a a -> PeriodicReport a b
    forall a a b. a -> PeriodicReport a b -> PeriodicReport a a
    forall a a b. (a -> b) -> PeriodicReport a a -> PeriodicReport a b
    forall (f :: * -> *).
    (forall a b. (a -> b) -> f a -> f b)
    -> (forall a b. a -> f b -> f a) -> Functor f
    $cfmap :: forall a a b. (a -> b) -> PeriodicReport a a -> PeriodicReport a b
    fmap :: forall a b. (a -> b) -> PeriodicReport a a -> PeriodicReport a b
    $c<$ :: forall a a b. a -> PeriodicReport a b -> PeriodicReport a a
    <$ :: forall a b. a -> PeriodicReport a b -> PeriodicReport a a
    Functor, (forall x. PeriodicReport a b -> Rep (PeriodicReport a b) x)
    -> (forall x. Rep (PeriodicReport a b) x -> PeriodicReport a b)
    -> Generic (PeriodicReport a b)
    forall x. Rep (PeriodicReport a b) x -> PeriodicReport a b
    forall x. PeriodicReport a b -> Rep (PeriodicReport a b) x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    forall a b x. Rep (PeriodicReport a b) x -> PeriodicReport a b
    forall a b x. PeriodicReport a b -> Rep (PeriodicReport a b) x
    $cfrom :: forall a b x. PeriodicReport a b -> Rep (PeriodicReport a b) x
    from :: forall x. PeriodicReport a b -> Rep (PeriodicReport a b) x
    $cto :: forall a b x. Rep (PeriodicReport a b) x -> PeriodicReport a b
    to :: forall x. Rep (PeriodicReport a b) x -> PeriodicReport a b
    Generic, [PeriodicReport a b] -> Value
    [PeriodicReport a b] -> Encoding
    PeriodicReport a b -> Value
    PeriodicReport a b -> Encoding
    (PeriodicReport a b -> Value)
    -> (PeriodicReport a b -> Encoding)
    -> ([PeriodicReport a b] -> Value)
    -> ([PeriodicReport a b] -> Encoding)
    -> ToJSON (PeriodicReport a b)
    forall a.
    (a -> Value)
    -> (a -> Encoding)
    -> ([a] -> Value)
    -> ([a] -> Encoding)
    -> ToJSON a
    forall a b. (ToJSON a, ToJSON b) => [PeriodicReport a b] -> Value
    forall a b.
    (ToJSON a, ToJSON b) =>
    [PeriodicReport a b] -> Encoding
    forall a b. (ToJSON a, ToJSON b) => PeriodicReport a b -> Value
    forall a b. (ToJSON a, ToJSON b) => PeriodicReport a b -> Encoding
    $ctoJSON :: forall a b. (ToJSON a, ToJSON b) => PeriodicReport a b -> Value
    toJSON :: PeriodicReport a b -> Value
    $ctoEncoding :: forall a b. (ToJSON a, ToJSON b) => PeriodicReport a b -> Encoding
    toEncoding :: PeriodicReport a b -> Encoding
    $ctoJSONList :: forall a b. (ToJSON a, ToJSON b) => [PeriodicReport a b] -> Value
    toJSONList :: [PeriodicReport a b] -> Value
    $ctoEncodingList :: forall a b.
    (ToJSON a, ToJSON b) =>
    [PeriodicReport a b] -> Encoding
    toEncodingList :: [PeriodicReport a b] -> Encoding
    ToJSON)

    instance Bifunctor PeriodicReport where
      bimap :: forall a b c d.
    (a -> b) -> (c -> d) -> PeriodicReport a c -> PeriodicReport b d
    bimap a -> b
    f c -> d
    g PeriodicReport a c
    pr = PeriodicReport a c
    pr{prRows :: [PeriodicReportRow b d]
    prRows = (PeriodicReportRow a c -> PeriodicReportRow b d)
    -> [PeriodicReportRow a c] -> [PeriodicReportRow b d]
    forall a b. (a -> b) -> [a] -> [b]
    map ((a -> b)
    -> (c -> d) -> PeriodicReportRow a c -> PeriodicReportRow b d
    forall a b c d.
    (a -> b)
    -> (c -> d) -> PeriodicReportRow a c -> PeriodicReportRow b d
    forall (p :: * -> * -> *) a b c d.
    Bifunctor p =>
    (a -> b) -> (c -> d) -> p a c -> p b d
    bimap a -> b
    f c -> d
    g) ([PeriodicReportRow a c] -> [PeriodicReportRow b d])
    -> [PeriodicReportRow a c] -> [PeriodicReportRow b d]
    forall a b. (a -> b) -> a -> b
    $ PeriodicReport a c -> [PeriodicReportRow a c]
    forall a b. PeriodicReport a b -> [PeriodicReportRow a b]
    prRows PeriodicReport a c
    pr, prTotals :: PeriodicReportRow () d
    prTotals = c -> d
    g (c -> d) -> PeriodicReportRow () c -> PeriodicReportRow () d
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> PeriodicReport a c -> PeriodicReportRow () c
    forall a b. PeriodicReport a b -> PeriodicReportRow () b
    prTotals PeriodicReport a c
    pr}

    data PeriodicReportRow a b =
      PeriodicReportRow
      { forall a b. PeriodicReportRow a b -> a
    prrName    :: a    -- An account name.
      , forall a b. PeriodicReportRow a b -> [b]
    prrAmounts :: [b]  -- The data value for each subperiod.
      , forall a b. PeriodicReportRow a b -> b
    prrTotal   :: b    -- The total of this row's values.
      , forall a b. PeriodicReportRow a b -> b
    prrAverage :: b    -- The average of this row's values.
      } deriving (Int -> PeriodicReportRow a b -> ShowS
    [PeriodicReportRow a b] -> ShowS
    PeriodicReportRow a b -> String
    (Int -> PeriodicReportRow a b -> ShowS)
    -> (PeriodicReportRow a b -> String)
    -> ([PeriodicReportRow a b] -> ShowS)
    -> Show (PeriodicReportRow a b)
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    forall a b.
    (Show a, Show b) =>
    Int -> PeriodicReportRow a b -> ShowS
    forall a b. (Show a, Show b) => [PeriodicReportRow a b] -> ShowS
    forall a b. (Show a, Show b) => PeriodicReportRow a b -> String
    $cshowsPrec :: forall a b.
    (Show a, Show b) =>
    Int -> PeriodicReportRow a b -> ShowS
    showsPrec :: Int -> PeriodicReportRow a b -> ShowS
    $cshow :: forall a b. (Show a, Show b) => PeriodicReportRow a b -> String
    show :: PeriodicReportRow a b -> String
    $cshowList :: forall a b. (Show a, Show b) => [PeriodicReportRow a b] -> ShowS
    showList :: [PeriodicReportRow a b] -> ShowS
    Show, (forall a b.
     (a -> b) -> PeriodicReportRow a a -> PeriodicReportRow a b)
    -> (forall a b.
        a -> PeriodicReportRow a b -> PeriodicReportRow a a)
    -> Functor (PeriodicReportRow a)
    forall a b. a -> PeriodicReportRow a b -> PeriodicReportRow a a
    forall a b.
    (a -> b) -> PeriodicReportRow a a -> PeriodicReportRow a b
    forall a a b. a -> PeriodicReportRow a b -> PeriodicReportRow a a
    forall a a b.
    (a -> b) -> PeriodicReportRow a a -> PeriodicReportRow a b
    forall (f :: * -> *).
    (forall a b. (a -> b) -> f a -> f b)
    -> (forall a b. a -> f b -> f a) -> Functor f
    $cfmap :: forall a a b.
    (a -> b) -> PeriodicReportRow a a -> PeriodicReportRow a b
    fmap :: forall a b.
    (a -> b) -> PeriodicReportRow a a -> PeriodicReportRow a b
    $c<$ :: forall a a b. a -> PeriodicReportRow a b -> PeriodicReportRow a a
    <$ :: forall a b. a -> PeriodicReportRow a b -> PeriodicReportRow a a
    Functor, (forall x. PeriodicReportRow a b -> Rep (PeriodicReportRow a b) x)
    -> (forall x.
        Rep (PeriodicReportRow a b) x -> PeriodicReportRow a b)
    -> Generic (PeriodicReportRow a b)
    forall x. Rep (PeriodicReportRow a b) x -> PeriodicReportRow a b
    forall x. PeriodicReportRow a b -> Rep (PeriodicReportRow a b) x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    forall a b x.
    Rep (PeriodicReportRow a b) x -> PeriodicReportRow a b
    forall a b x.
    PeriodicReportRow a b -> Rep (PeriodicReportRow a b) x
    $cfrom :: forall a b x.
    PeriodicReportRow a b -> Rep (PeriodicReportRow a b) x
    from :: forall x. PeriodicReportRow a b -> Rep (PeriodicReportRow a b) x
    $cto :: forall a b x.
    Rep (PeriodicReportRow a b) x -> PeriodicReportRow a b
    to :: forall x. Rep (PeriodicReportRow a b) x -> PeriodicReportRow a b
    Generic, [PeriodicReportRow a b] -> Value
    [PeriodicReportRow a b] -> Encoding
    PeriodicReportRow a b -> Value
    PeriodicReportRow a b -> Encoding
    (PeriodicReportRow a b -> Value)
    -> (PeriodicReportRow a b -> Encoding)
    -> ([PeriodicReportRow a b] -> Value)
    -> ([PeriodicReportRow a b] -> Encoding)
    -> ToJSON (PeriodicReportRow a b)
    forall a.
    (a -> Value)
    -> (a -> Encoding)
    -> ([a] -> Value)
    -> ([a] -> Encoding)
    -> ToJSON a
    forall a b.
    (ToJSON b, ToJSON a) =>
    [PeriodicReportRow a b] -> Value
    forall a b.
    (ToJSON b, ToJSON a) =>
    [PeriodicReportRow a b] -> Encoding
    forall a b. (ToJSON b, ToJSON a) => PeriodicReportRow a b -> Value
    forall a b.
    (ToJSON b, ToJSON a) =>
    PeriodicReportRow a b -> Encoding
    $ctoJSON :: forall a b. (ToJSON b, ToJSON a) => PeriodicReportRow a b -> Value
    toJSON :: PeriodicReportRow a b -> Value
    $ctoEncoding :: forall a b.
    (ToJSON b, ToJSON a) =>
    PeriodicReportRow a b -> Encoding
    toEncoding :: PeriodicReportRow a b -> Encoding
    $ctoJSONList :: forall a b.
    (ToJSON b, ToJSON a) =>
    [PeriodicReportRow a b] -> Value
    toJSONList :: [PeriodicReportRow a b] -> Value
    $ctoEncodingList :: forall a b.
    (ToJSON b, ToJSON a) =>
    [PeriodicReportRow a b] -> Encoding
    toEncodingList :: [PeriodicReportRow a b] -> Encoding
    ToJSON)

    instance Bifunctor PeriodicReportRow where
      first :: forall a b c.
    (a -> b) -> PeriodicReportRow a c -> PeriodicReportRow b c
    first a -> b
    f PeriodicReportRow a c
    prr = PeriodicReportRow a c
    prr{prrName :: b
    prrName = a -> b
    f (a -> b) -> a -> b
    forall a b. (a -> b) -> a -> b
    $ PeriodicReportRow a c -> a
    forall a b. PeriodicReportRow a b -> a
    prrName PeriodicReportRow a c
    prr}
      second :: forall b c a.
    (b -> c) -> PeriodicReportRow a b -> PeriodicReportRow a c
    second = (b -> c) -> PeriodicReportRow a b -> PeriodicReportRow a c
    forall a b.
    (a -> b) -> PeriodicReportRow a a -> PeriodicReportRow a b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap

    instance Semigroup b => Semigroup (PeriodicReportRow a b) where
      <> :: PeriodicReportRow a b
    -> PeriodicReportRow a b -> PeriodicReportRow a b
    (<>) = PeriodicReportRow a b
    -> PeriodicReportRow a b -> PeriodicReportRow a b
    forall b a.
    Semigroup b =>
    PeriodicReportRow a b
    -> PeriodicReportRow a b -> PeriodicReportRow a b
    prrAdd

    -- | Add two 'PeriodicReportRows', preserving the name of the first.
    prrAdd :: Semigroup b => PeriodicReportRow a b -> PeriodicReportRow a b -> PeriodicReportRow a b
    prrAdd :: forall b a.
    Semigroup b =>
    PeriodicReportRow a b
    -> PeriodicReportRow a b -> PeriodicReportRow a b
    prrAdd (PeriodicReportRow a
    n1 [b]
    amts1 b
    t1 b
    a1) (PeriodicReportRow a
    _ [b]
    amts2 b
    t2 b
    a2) =
        a -> [b] -> b -> b -> PeriodicReportRow a b
    forall a b. a -> [b] -> b -> b -> PeriodicReportRow a b
    PeriodicReportRow a
    n1 ((b -> b -> b) -> [b] -> [b] -> [b]
    forall a. (a -> a -> a) -> [a] -> [a] -> [a]
    zipWithPadded b -> b -> b
    forall a. Semigroup a => a -> a -> a
    (<>) [b]
    amts1 [b]
    amts2) (b
    t1 b -> b -> b
    forall a. Semigroup a => a -> a -> a
    <> b
    t2) (b
    a1 b -> b -> b
    forall a. Semigroup a => a -> a -> a
    <> b
    a2)

    -- | Version of 'zipWith' which will not end on the shortest list, but will copy the rest of the longer list.
    zipWithPadded :: (a -> a -> a) -> [a] -> [a] -> [a]
    zipWithPadded :: forall a. (a -> a -> a) -> [a] -> [a] -> [a]
    zipWithPadded a -> a -> a
    f (a
    a:[a]
    as) (a
    b:[a]
    bs) = a -> a -> a
    f a
    a a
    b a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : (a -> a -> a) -> [a] -> [a] -> [a]
    forall a. (a -> a -> a) -> [a] -> [a] -> [a]
    zipWithPadded a -> a -> a
    f [a]
    as [a]
    bs
    zipWithPadded a -> a -> a
    _ [a]
    as     []     = [a]
    as
    zipWithPadded a -> a -> a
    _ []     [a]
    bs     = [a]
    bs

    -- | Figure out the overall date span of a PeriodicReport
    periodicReportSpan :: PeriodicReport a b -> DateSpan
    periodicReportSpan :: forall a b. PeriodicReport a b -> DateSpan
    periodicReportSpan (PeriodicReport [] [PeriodicReportRow a b]
    _ PeriodicReportRow () b
    _)       = Maybe EFDay -> Maybe EFDay -> DateSpan
    DateSpan Maybe EFDay
    forall a. Maybe a
    Nothing Maybe EFDay
    forall a. Maybe a
    Nothing
    periodicReportSpan (PeriodicReport [DateSpan]
    colspans [PeriodicReportRow a b]
    _ PeriodicReportRow () b
    _) = Maybe EFDay -> Maybe EFDay -> DateSpan
    DateSpan ((Day -> EFDay) -> Maybe Day -> Maybe EFDay
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Day -> EFDay
    Exact (Maybe Day -> Maybe EFDay)
    -> (DateSpan -> Maybe Day) -> DateSpan -> Maybe EFDay
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DateSpan -> Maybe Day
    spanStart (DateSpan -> Maybe EFDay) -> DateSpan -> Maybe EFDay
    forall a b. (a -> b) -> a -> b
    $ [DateSpan] -> DateSpan
    forall a. HasCallStack => [a] -> a
    head [DateSpan]
    colspans) ((Day -> EFDay) -> Maybe Day -> Maybe EFDay
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Day -> EFDay
    Exact (Maybe Day -> Maybe EFDay)
    -> (DateSpan -> Maybe Day) -> DateSpan -> Maybe EFDay
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DateSpan -> Maybe Day
    spanEnd (DateSpan -> Maybe EFDay) -> DateSpan -> Maybe EFDay
    forall a b. (a -> b) -> a -> b
    $ [DateSpan] -> DateSpan
    forall a. HasCallStack => [a] -> a
    last [DateSpan]
    colspans)

    -- | Map a function over the row names.
    prMapName :: (a -> b) -> PeriodicReport a c -> PeriodicReport b c
    prMapName :: forall a b c. (a -> b) -> PeriodicReport a c -> PeriodicReport b c
    prMapName a -> b
    f PeriodicReport a c
    report = PeriodicReport a c
    report{prRows :: [PeriodicReportRow b c]
    prRows = (PeriodicReportRow a c -> PeriodicReportRow b c)
    -> [PeriodicReportRow a c] -> [PeriodicReportRow b c]
    forall a b. (a -> b) -> [a] -> [b]
    map ((a -> b) -> PeriodicReportRow a c -> PeriodicReportRow b c
    forall a b c.
    (a -> b) -> PeriodicReportRow a c -> PeriodicReportRow b c
    prrMapName a -> b
    f) ([PeriodicReportRow a c] -> [PeriodicReportRow b c])
    -> [PeriodicReportRow a c] -> [PeriodicReportRow b c]
    forall a b. (a -> b) -> a -> b
    $ PeriodicReport a c -> [PeriodicReportRow a c]
    forall a b. PeriodicReport a b -> [PeriodicReportRow a b]
    prRows PeriodicReport a c
    report}

    -- | Map a function over the row names, possibly discarding some.
    prMapMaybeName :: (a -> Maybe b) -> PeriodicReport a c -> PeriodicReport b c
    prMapMaybeName :: forall a b c.
    (a -> Maybe b) -> PeriodicReport a c -> PeriodicReport b c
    prMapMaybeName a -> Maybe b
    f PeriodicReport a c
    report = PeriodicReport a c
    report{prRows :: [PeriodicReportRow b c]
    prRows = (PeriodicReportRow a c -> Maybe (PeriodicReportRow b c))
    -> [PeriodicReportRow a c] -> [PeriodicReportRow b c]
    forall a b. (a -> Maybe b) -> [a] -> [b]
    mapMaybe ((a -> Maybe b)
    -> PeriodicReportRow a c -> Maybe (PeriodicReportRow b c)
    forall a b c.
    (a -> Maybe b)
    -> PeriodicReportRow a c -> Maybe (PeriodicReportRow b c)
    prrMapMaybeName a -> Maybe b
    f) ([PeriodicReportRow a c] -> [PeriodicReportRow b c])
    -> [PeriodicReportRow a c] -> [PeriodicReportRow b c]
    forall a b. (a -> b) -> a -> b
    $ PeriodicReport a c -> [PeriodicReportRow a c]
    forall a b. PeriodicReport a b -> [PeriodicReportRow a b]
    prRows PeriodicReport a c
    report}

    -- | Map a function over the row names of the PeriodicReportRow.
    prrMapName :: (a -> b) -> PeriodicReportRow a c -> PeriodicReportRow b c
    prrMapName :: forall a b c.
    (a -> b) -> PeriodicReportRow a c -> PeriodicReportRow b c
    prrMapName a -> b
    f PeriodicReportRow a c
    row = PeriodicReportRow a c
    row{prrName :: b
    prrName = a -> b
    f (a -> b) -> a -> b
    forall a b. (a -> b) -> a -> b
    $ PeriodicReportRow a c -> a
    forall a b. PeriodicReportRow a b -> a
    prrName PeriodicReportRow a c
    row}

    -- | Map maybe a function over the row names of the PeriodicReportRow.
    prrMapMaybeName :: (a -> Maybe b) -> PeriodicReportRow a c -> Maybe (PeriodicReportRow b c)
    prrMapMaybeName :: forall a b c.
    (a -> Maybe b)
    -> PeriodicReportRow a c -> Maybe (PeriodicReportRow b c)
    prrMapMaybeName a -> Maybe b
    f PeriodicReportRow a c
    row = case a -> Maybe b
    f (a -> Maybe b) -> a -> Maybe b
    forall a b. (a -> b) -> a -> b
    $ PeriodicReportRow a c -> a
    forall a b. PeriodicReportRow a b -> a
    prrName PeriodicReportRow a c
    row of
        Maybe b
    Nothing -> Maybe (PeriodicReportRow b c)
    forall a. Maybe a
    Nothing
        Just b
    a  -> PeriodicReportRow b c -> Maybe (PeriodicReportRow b c)
    forall a. a -> Maybe a
    Just PeriodicReportRow a c
    row{prrName :: b
    prrName = b
    a}

    -- | A compound balance report has:
    --
    -- * an overall title
    --
    -- * the period (date span) of each column
    --
    -- * one or more named, normal-positive multi balance reports,
    --   with columns corresponding to the above, and a flag indicating
    --   whether they increased or decreased the overall totals
    --
    -- * a list of overall totals for each column, and their grand total and average
    --
    -- It is used in compound balance report commands like balancesheet,
    -- cashflow and incomestatement.
    data CompoundPeriodicReport a b = CompoundPeriodicReport
      { forall a b. CompoundPeriodicReport a b -> Text
    cbrTitle      :: Text
      , forall a b. CompoundPeriodicReport a b -> [DateSpan]
    cbrDates      :: [DateSpan]
      , forall a b.
    CompoundPeriodicReport a b -> [(Text, PeriodicReport a b, Bool)]
    cbrSubreports :: [(Text, PeriodicReport a b, Bool)]
      , forall a b. CompoundPeriodicReport a b -> PeriodicReportRow () b
    cbrTotals     :: PeriodicReportRow () b
      } deriving (Int -> CompoundPeriodicReport a b -> ShowS
    [CompoundPeriodicReport a b] -> ShowS
    CompoundPeriodicReport a b -> String
    (Int -> CompoundPeriodicReport a b -> ShowS)
    -> (CompoundPeriodicReport a b -> String)
    -> ([CompoundPeriodicReport a b] -> ShowS)
    -> Show (CompoundPeriodicReport a b)
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    forall a b.
    (Show a, Show b) =>
    Int -> CompoundPeriodicReport a b -> ShowS
    forall a b.
    (Show a, Show b) =>
    [CompoundPeriodicReport a b] -> ShowS
    forall a b.
    (Show a, Show b) =>
    CompoundPeriodicReport a b -> String
    $cshowsPrec :: forall a b.
    (Show a, Show b) =>
    Int -> CompoundPeriodicReport a b -> ShowS
    showsPrec :: Int -> CompoundPeriodicReport a b -> ShowS
    $cshow :: forall a b.
    (Show a, Show b) =>
    CompoundPeriodicReport a b -> String
    show :: CompoundPeriodicReport a b -> String
    $cshowList :: forall a b.
    (Show a, Show b) =>
    [CompoundPeriodicReport a b] -> ShowS
    showList :: [CompoundPeriodicReport a b] -> ShowS
    Show, (forall a b.
     (a -> b)
     -> CompoundPeriodicReport a a -> CompoundPeriodicReport a b)
    -> (forall a b.
        a -> CompoundPeriodicReport a b -> CompoundPeriodicReport a a)
    -> Functor (CompoundPeriodicReport a)
    forall a b.
    a -> CompoundPeriodicReport a b -> CompoundPeriodicReport a a
    forall a b.
    (a -> b)
    -> CompoundPeriodicReport a a -> CompoundPeriodicReport a b
    forall a a b.
    a -> CompoundPeriodicReport a b -> CompoundPeriodicReport a a
    forall a a b.
    (a -> b)
    -> CompoundPeriodicReport a a -> CompoundPeriodicReport a b
    forall (f :: * -> *).
    (forall a b. (a -> b) -> f a -> f b)
    -> (forall a b. a -> f b -> f a) -> Functor f
    $cfmap :: forall a a b.
    (a -> b)
    -> CompoundPeriodicReport a a -> CompoundPeriodicReport a b
    fmap :: forall a b.
    (a -> b)
    -> CompoundPeriodicReport a a -> CompoundPeriodicReport a b
    $c<$ :: forall a a b.
    a -> CompoundPeriodicReport a b -> CompoundPeriodicReport a a
    <$ :: forall a b.
    a -> CompoundPeriodicReport a b -> CompoundPeriodicReport a a
    Functor, (forall x.
     CompoundPeriodicReport a b -> Rep (CompoundPeriodicReport a b) x)
    -> (forall x.
        Rep (CompoundPeriodicReport a b) x -> CompoundPeriodicReport a b)
    -> Generic (CompoundPeriodicReport a b)
    forall x.
    Rep (CompoundPeriodicReport a b) x -> CompoundPeriodicReport a b
    forall x.
    CompoundPeriodicReport a b -> Rep (CompoundPeriodicReport a b) x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    forall a b x.
    Rep (CompoundPeriodicReport a b) x -> CompoundPeriodicReport a b
    forall a b x.
    CompoundPeriodicReport a b -> Rep (CompoundPeriodicReport a b) x
    $cfrom :: forall a b x.
    CompoundPeriodicReport a b -> Rep (CompoundPeriodicReport a b) x
    from :: forall x.
    CompoundPeriodicReport a b -> Rep (CompoundPeriodicReport a b) x
    $cto :: forall a b x.
    Rep (CompoundPeriodicReport a b) x -> CompoundPeriodicReport a b
    to :: forall x.
    Rep (CompoundPeriodicReport a b) x -> CompoundPeriodicReport a b
    Generic, [CompoundPeriodicReport a b] -> Value
    [CompoundPeriodicReport a b] -> Encoding
    CompoundPeriodicReport a b -> Value
    CompoundPeriodicReport a b -> Encoding
    (CompoundPeriodicReport a b -> Value)
    -> (CompoundPeriodicReport a b -> Encoding)
    -> ([CompoundPeriodicReport a b] -> Value)
    -> ([CompoundPeriodicReport a b] -> Encoding)
    -> ToJSON (CompoundPeriodicReport a b)
    forall a.
    (a -> Value)
    -> (a -> Encoding)
    -> ([a] -> Value)
    -> ([a] -> Encoding)
    -> ToJSON a
    forall a b.
    (ToJSON b, ToJSON a) =>
    [CompoundPeriodicReport a b] -> Value
    forall a b.
    (ToJSON b, ToJSON a) =>
    [CompoundPeriodicReport a b] -> Encoding
    forall a b.
    (ToJSON b, ToJSON a) =>
    CompoundPeriodicReport a b -> Value
    forall a b.
    (ToJSON b, ToJSON a) =>
    CompoundPeriodicReport a b -> Encoding
    $ctoJSON :: forall a b.
    (ToJSON b, ToJSON a) =>
    CompoundPeriodicReport a b -> Value
    toJSON :: CompoundPeriodicReport a b -> Value
    $ctoEncoding :: forall a b.
    (ToJSON b, ToJSON a) =>
    CompoundPeriodicReport a b -> Encoding
    toEncoding :: CompoundPeriodicReport a b -> Encoding
    $ctoJSONList :: forall a b.
    (ToJSON b, ToJSON a) =>
    [CompoundPeriodicReport a b] -> Value
    toJSONList :: [CompoundPeriodicReport a b] -> Value
    $ctoEncodingList :: forall a b.
    (ToJSON b, ToJSON a) =>
    [CompoundPeriodicReport a b] -> Encoding
    toEncodingList :: [CompoundPeriodicReport a b] -> Encoding
    ToJSON)

    -- | Description of one subreport within a compound balance report.
    -- Part of a "CompoundBalanceCommandSpec", but also used in hledger-lib.
    data CBCSubreportSpec a = CBCSubreportSpec
      { forall a. CBCSubreportSpec a -> Text
    cbcsubreporttitle          :: Text                      -- ^ The title to use for the subreport
      , forall a. CBCSubreportSpec a -> Query
    cbcsubreportquery          :: Query                     -- ^ The Query to use for the subreport
      , forall a. CBCSubreportSpec a -> ReportOpts -> ReportOpts
    cbcsubreportoptions        :: ReportOpts -> ReportOpts  -- ^ A function to transform the ReportOpts used to produce the subreport
      , forall a.
    CBCSubreportSpec a
    -> PeriodicReport DisplayName MixedAmount
    -> PeriodicReport a MixedAmount
    cbcsubreporttransform      :: PeriodicReport DisplayName MixedAmount -> PeriodicReport a MixedAmount  -- ^ A function to transform the result of the subreport
      , forall a. CBCSubreportSpec a -> Bool
    cbcsubreportincreasestotal :: Bool                      -- ^ Whether the subreport and overall report total are of the same sign (e.g. Assets are normally
                                                                --   positive in a balance sheet report, as is the overall total. Liabilities are normally of the
                                                                --   opposite sign.)
      }

    -- | A full name, display name, and depth for an account.
    data DisplayName = DisplayName
        { DisplayName -> Text
    displayFull :: AccountName
        , DisplayName -> Text
    displayName :: AccountName
        , DisplayName -> Int
    displayDepth :: Int
        } deriving (Int -> DisplayName -> ShowS
    [DisplayName] -> ShowS
    DisplayName -> String
    (Int -> DisplayName -> ShowS)
    -> (DisplayName -> String)
    -> ([DisplayName] -> ShowS)
    -> Show DisplayName
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> DisplayName -> ShowS
    showsPrec :: Int -> DisplayName -> ShowS
    $cshow :: DisplayName -> String
    show :: DisplayName -> String
    $cshowList :: [DisplayName] -> ShowS
    showList :: [DisplayName] -> ShowS
    Show, DisplayName -> DisplayName -> Bool
    (DisplayName -> DisplayName -> Bool)
    -> (DisplayName -> DisplayName -> Bool) -> Eq DisplayName
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: DisplayName -> DisplayName -> Bool
    == :: DisplayName -> DisplayName -> Bool
    $c/= :: DisplayName -> DisplayName -> Bool
    /= :: DisplayName -> DisplayName -> Bool
    Eq, Eq DisplayName
    Eq DisplayName
    -> (DisplayName -> DisplayName -> Ordering)
    -> (DisplayName -> DisplayName -> Bool)
    -> (DisplayName -> DisplayName -> Bool)
    -> (DisplayName -> DisplayName -> Bool)
    -> (DisplayName -> DisplayName -> Bool)
    -> (DisplayName -> DisplayName -> DisplayName)
    -> (DisplayName -> DisplayName -> DisplayName)
    -> Ord DisplayName
    DisplayName -> DisplayName -> Bool
    DisplayName -> DisplayName -> Ordering
    DisplayName -> DisplayName -> DisplayName
    forall a.
    Eq a
    -> (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: DisplayName -> DisplayName -> Ordering
    compare :: DisplayName -> DisplayName -> Ordering
    $c< :: DisplayName -> DisplayName -> Bool
    < :: DisplayName -> DisplayName -> Bool
    $c<= :: DisplayName -> DisplayName -> Bool
    <= :: DisplayName -> DisplayName -> Bool
    $c> :: DisplayName -> DisplayName -> Bool
    > :: DisplayName -> DisplayName -> Bool
    $c>= :: DisplayName -> DisplayName -> Bool
    >= :: DisplayName -> DisplayName -> Bool
    $cmax :: DisplayName -> DisplayName -> DisplayName
    max :: DisplayName -> DisplayName -> DisplayName
    $cmin :: DisplayName -> DisplayName -> DisplayName
    min :: DisplayName -> DisplayName -> DisplayName
    Ord)

    instance ToJSON DisplayName where
        toJSON :: DisplayName -> Value
    toJSON = Text -> Value
    forall a. ToJSON a => a -> Value
    toJSON (Text -> Value) -> (DisplayName -> Text) -> DisplayName -> Value
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DisplayName -> Text
    displayFull
        toEncoding :: DisplayName -> Encoding
    toEncoding = Text -> Encoding
    forall a. ToJSON a => a -> Encoding
    toEncoding (Text -> Encoding)
    -> (DisplayName -> Text) -> DisplayName -> Encoding
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DisplayName -> Text
    displayFull

    -- | Construct a flat display name, where the full name is also displayed at
    -- depth 1
    flatDisplayName :: AccountName -> DisplayName
    flatDisplayName :: Text -> DisplayName
    flatDisplayName Text
    a = Text -> Text -> Int -> DisplayName
    DisplayName Text
    a Text
    a Int
    1

    -- | Construct a tree display name, where only the leaf is displayed at its
    -- given depth
    treeDisplayName :: AccountName -> DisplayName
    treeDisplayName :: Text -> DisplayName
    treeDisplayName Text
    a = Text -> Text -> Int -> DisplayName
    DisplayName Text
    a (Text -> Text
    accountLeafName Text
    a) (Text -> Int
    accountNameLevel Text
    a)

    -- | Get the full, canonical, name of a PeriodicReportRow tagged by a
    -- DisplayName.
    prrFullName :: PeriodicReportRow DisplayName a -> AccountName
    prrFullName :: forall a. PeriodicReportRow DisplayName a -> Text
    prrFullName = DisplayName -> Text
    displayFull (DisplayName -> Text)
    -> (PeriodicReportRow DisplayName a -> DisplayName)
    -> PeriodicReportRow DisplayName a
    -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PeriodicReportRow DisplayName a -> DisplayName
    forall a b. PeriodicReportRow a b -> a
    prrName

    -- | Get the display name of a PeriodicReportRow tagged by a DisplayName.
    prrDisplayName :: PeriodicReportRow DisplayName a -> AccountName
    prrDisplayName :: forall a. PeriodicReportRow DisplayName a -> Text
    prrDisplayName = DisplayName -> Text
    displayName (DisplayName -> Text)
    -> (PeriodicReportRow DisplayName a -> DisplayName)
    -> PeriodicReportRow DisplayName a
    -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PeriodicReportRow DisplayName a -> DisplayName
    forall a b. PeriodicReportRow a b -> a
    prrName

    -- | Get the display depth of a PeriodicReportRow tagged by a DisplayName.
    prrDepth :: PeriodicReportRow DisplayName a -> Int
    prrDepth :: forall a. PeriodicReportRow DisplayName a -> Int
    prrDepth = DisplayName -> Int
    displayDepth (DisplayName -> Int)
    -> (PeriodicReportRow DisplayName a -> DisplayName)
    -> PeriodicReportRow DisplayName a
    -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PeriodicReportRow DisplayName a -> DisplayName
    forall a b. PeriodicReportRow a b -> a
    prrName