{-|

The @payees@ command lists all unique payees (description part before a |) seen in transactions, sorted alphabetically.

-}

{-# LANGUAGE MultiWayIf          #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell     #-}

module Hledger.Cli.Commands.Payees (
  payeesmode
 ,payees
) where

import qualified Data.Text.IO as T
import System.Console.CmdArgs.Explicit

import Hledger
import Hledger.Cli.CliOptions
import Data.List ((\\))
import Data.List.Extra (nubSort)


-- | Command line options for this command.
payeesmode :: Mode RawOpts
payeesmode = CommandHelpStr
-> [Flag RawOpts]
-> [(CommandHelpStr, [Flag RawOpts])]
-> [Flag RawOpts]
-> ([Arg RawOpts], Maybe (Arg RawOpts))
-> Mode RawOpts
hledgerCommandMode
  $(embedFileRelative "Hledger/Cli/Commands/Payees.txt")
  [[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"used"]         (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"used")       CommandHelpStr
"list payees used"
  ,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"declared"]     (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"declared")   CommandHelpStr
"list payees declared"
  ,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"undeclared"]   (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"undeclared") CommandHelpStr
"list payees used but not declared"
  ,[CommandHelpStr]
-> (RawOpts -> RawOpts) -> CommandHelpStr -> Flag RawOpts
forall a. [CommandHelpStr] -> (a -> a) -> CommandHelpStr -> Flag a
flagNone [CommandHelpStr
"unused"]       (CommandHelpStr -> RawOpts -> RawOpts
setboolopt CommandHelpStr
"unused")     CommandHelpStr
"list payees declared but not used"
  ]
  [(CommandHelpStr, [Flag RawOpts])]
cligeneralflagsgroups1
  [Flag RawOpts]
hiddenflags
  ([], Arg RawOpts -> Maybe (Arg RawOpts)
forall a. a -> Maybe a
Just (Arg RawOpts -> Maybe (Arg RawOpts))
-> Arg RawOpts -> Maybe (Arg RawOpts)
forall a b. (a -> b) -> a -> b
$ CommandHelpStr -> Arg RawOpts
argsFlag CommandHelpStr
"[QUERY..]")

-- | The payees command.
payees :: CliOpts -> Journal -> IO ()
payees :: CliOpts -> Journal -> IO ()
payees opts :: CliOpts
opts@CliOpts{reportspec_ :: CliOpts -> ReportSpec
reportspec_=ReportSpec{_rsQuery :: ReportSpec -> Query
_rsQuery=Query
query}} Journal
j = do
  let
    -- XXX matchesPayeeWIP is currently an alias for matchesDescription, not sure if it matters
    matchedused :: [Text]
matchedused       = CommandHelpStr -> [Text] -> [Text]
forall a. Show a => CommandHelpStr -> a -> a
dbg5 CommandHelpStr
"matchedused"       ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
forall a. Ord a => [a] -> [a]
nubSort ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ (Transaction -> Text) -> [Transaction] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Transaction -> Text
transactionPayee ([Transaction] -> [Text]) -> [Transaction] -> [Text]
forall a b. (a -> b) -> a -> b
$ (Transaction -> Bool) -> [Transaction] -> [Transaction]
forall a. (a -> Bool) -> [a] -> [a]
filter (Query -> Transaction -> Bool
matchesTransaction Query
query) ([Transaction] -> [Transaction]) -> [Transaction] -> [Transaction]
forall a b. (a -> b) -> a -> b
$ Journal -> [Transaction]
jtxns Journal
j
    matcheddeclared :: [Text]
matcheddeclared   = CommandHelpStr -> [Text] -> [Text]
forall a. Show a => CommandHelpStr -> a -> a
dbg5 CommandHelpStr
"matcheddeclared"   ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
forall a. Ord a => [a] -> [a]
nubSort ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter (Query -> Text -> Bool
matchesPayeeWIP Query
query) ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ Journal -> [Text]
journalPayeesDeclared Journal
j
    matchedunused :: [Text]
matchedunused     = CommandHelpStr -> [Text] -> [Text]
forall a. Show a => CommandHelpStr -> a -> a
dbg5 CommandHelpStr
"matchedunused"     ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
forall a. Ord a => [a] -> [a]
nubSort ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text]
matcheddeclared [Text] -> [Text] -> [Text]
forall a. Eq a => [a] -> [a] -> [a]
\\ [Text]
matchedused
    matchedundeclared :: [Text]
matchedundeclared = CommandHelpStr -> [Text] -> [Text]
forall a. Show a => CommandHelpStr -> a -> a
dbg5 CommandHelpStr
"matchedundeclared" ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
forall a. Ord a => [a] -> [a]
nubSort ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text]
matchedused     [Text] -> [Text] -> [Text]
forall a. Eq a => [a] -> [a] -> [a]
\\ [Text]
matcheddeclared
    matchedall :: [Text]
matchedall        = CommandHelpStr -> [Text] -> [Text]
forall a. Show a => CommandHelpStr -> a -> a
dbg5 CommandHelpStr
"matchedall"        ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
forall a. Ord a => [a] -> [a]
nubSort ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text]
matcheddeclared [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text]
matchedused
  (Text -> IO ()) -> [Text] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Text -> IO ()
T.putStrLn ([Text] -> IO ()) -> [Text] -> IO ()
forall a b. (a -> b) -> a -> b
$ case CliOpts -> Maybe UsedOrDeclared
usedOrDeclaredFromOpts CliOpts
opts of
    Maybe UsedOrDeclared
Nothing         -> [Text]
matchedall
    Just UsedOrDeclared
Used       -> [Text]
matchedused
    Just UsedOrDeclared
Declared   -> [Text]
matcheddeclared
    Just UsedOrDeclared
Undeclared -> [Text]
matchedundeclared
    Just UsedOrDeclared
Unused     -> [Text]
matchedunused