{-# LANGUAGE OverloadedStrings, RecordWildCards, FlexibleInstances, ScopedTypeVariables #-}
{-|

Journal entries report, used by the print command.

-}

module Hledger.Reports.EntriesReport (
  EntriesReport,
  EntriesReportItem,
  entriesReport,
  -- * Tests
  tests_EntriesReport
)
where

import Data.List (sortBy)
import Data.Maybe (fromMaybe)
import Data.Ord (comparing)
import Data.Time (fromGregorian)

import Hledger.Data
import Hledger.Query
import Hledger.Reports.ReportOptions
import Hledger.Utils


-- | A journal entries report is a list of whole transactions as
-- originally entered in the journal (mostly). This is used by eg
-- hledger's print command and hledger-web's journal entries view.
type EntriesReport = [EntriesReportItem]
type EntriesReportItem = Transaction

-- | Select transactions for an entries report.
entriesReport :: ReportOpts -> Query -> Journal -> EntriesReport
entriesReport :: ReportOpts -> Query -> Journal -> EntriesReport
entriesReport ropts :: ReportOpts
ropts@ReportOpts{..} q :: Query
q j :: Journal
j@Journal{..} =
  (Transaction -> Transaction -> Ordering)
-> EntriesReport -> EntriesReport
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ((Transaction -> Day) -> Transaction -> Transaction -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing Transaction -> Day
getdate) (EntriesReport -> EntriesReport) -> EntriesReport -> EntriesReport
forall a b. (a -> b) -> a -> b
$ (Transaction -> Bool) -> EntriesReport -> EntriesReport
forall a. (a -> Bool) -> [a] -> [a]
filter (Query
q Query -> Transaction -> Bool
`matchesTransaction`) (EntriesReport -> EntriesReport) -> EntriesReport -> EntriesReport
forall a b. (a -> b) -> a -> b
$ (Transaction -> Transaction) -> EntriesReport -> EntriesReport
forall a b. (a -> b) -> [a] -> [b]
map Transaction -> Transaction
tvalue EntriesReport
jtxns
  where
    getdate :: Transaction -> Day
getdate = ReportOpts -> Transaction -> Day
transactionDateFn ReportOpts
ropts
    -- We may be converting posting amounts to value, per hledger_options.m4.md "Effect of --value on reports".
    tvalue :: Transaction -> Transaction
tvalue t :: Transaction
t@Transaction{..} = Transaction
t{tpostings :: [Posting]
tpostings=(Posting -> Posting) -> [Posting] -> [Posting]
forall a b. (a -> b) -> [a] -> [b]
map Posting -> Posting
pvalue [Posting]
tpostings}
      where
        pvalue :: Posting -> Posting
pvalue p :: Posting
p = Posting
-> (ValuationType -> Posting) -> Maybe ValuationType -> Posting
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Posting
p
          (PriceOracle
-> Map Text AmountStyle
-> Day
-> Maybe Day
-> Day
-> Bool
-> Posting
-> ValuationType
-> Posting
postingApplyValuation (Bool -> Journal -> PriceOracle
journalPriceOracle Bool
infer_value_ Journal
j) (Journal -> Map Text AmountStyle
journalCommodityStyles Journal
j) Day
periodlast Maybe Day
mreportlast Day
today Bool
False Posting
p)
          Maybe ValuationType
value_
          where
            periodlast :: Day
periodlast  = Day -> Maybe Day -> Day
forall a. a -> Maybe a -> a
fromMaybe Day
today (Maybe Day -> Day) -> Maybe Day -> Day
forall a b. (a -> b) -> a -> b
$ ReportOpts -> Journal -> Maybe Day
reportPeriodOrJournalLastDay ReportOpts
ropts Journal
j
            mreportlast :: Maybe Day
mreportlast = ReportOpts -> Maybe Day
reportPeriodLastDay ReportOpts
ropts
            today :: Day
today       = Day -> Maybe Day -> Day
forall a. a -> Maybe a -> a
fromMaybe (String -> Day
forall a. String -> a
error' "erValue: could not pick a valuation date, ReportOpts today_ is unset") Maybe Day
today_  -- PARTIAL: should not happen

tests_EntriesReport :: TestTree
tests_EntriesReport = String -> [TestTree] -> TestTree
tests "EntriesReport" [
  String -> [TestTree] -> TestTree
tests "entriesReport" [
     String -> Assertion -> TestTree
test "not acct" (Assertion -> TestTree) -> Assertion -> TestTree
forall a b. (a -> b) -> a -> b
$ (EntriesReport -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (EntriesReport -> Int) -> EntriesReport -> Int
forall a b. (a -> b) -> a -> b
$ ReportOpts -> Query -> Journal -> EntriesReport
entriesReport ReportOpts
defreportopts (Query -> Query
Not (Query -> Query) -> (Regexp -> Query) -> Regexp -> Query
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Regexp -> Query
Acct (Regexp -> Query) -> Regexp -> Query
forall a b. (a -> b) -> a -> b
$ String -> Regexp
toRegex' "bank") Journal
samplejournal) Int -> Int -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= 1
    ,String -> Assertion -> TestTree
test "date" (Assertion -> TestTree) -> Assertion -> TestTree
forall a b. (a -> b) -> a -> b
$ (EntriesReport -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (EntriesReport -> Int) -> EntriesReport -> Int
forall a b. (a -> b) -> a -> b
$ ReportOpts -> Query -> Journal -> EntriesReport
entriesReport ReportOpts
defreportopts (DateSpan -> Query
Date (DateSpan -> Query) -> DateSpan -> Query
forall a b. (a -> b) -> a -> b
$ Maybe Day -> Maybe Day -> DateSpan
DateSpan (Day -> Maybe Day
forall a. a -> Maybe a
Just (Day -> Maybe Day) -> Day -> Maybe Day
forall a b. (a -> b) -> a -> b
$ Year -> Int -> Int -> Day
fromGregorian 2008 06 01) (Day -> Maybe Day
forall a. a -> Maybe a
Just (Day -> Maybe Day) -> Day -> Maybe Day
forall a b. (a -> b) -> a -> b
$ Year -> Int -> Int -> Day
fromGregorian 2008 07 01)) Journal
samplejournal) Int -> Int -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= 3
  ]
 ]