{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
module Hledger.Data.Posting (
nullposting,
posting,
post,
vpost,
post',
vpost',
nullsourcepos,
nullassertion,
balassert,
balassertTot,
balassertParInc,
balassertTotInc,
originalPosting,
postingStatus,
isReal,
isVirtual,
isBalancedVirtual,
isEmptyPosting,
hasBalanceAssignment,
hasAmount,
postingAllTags,
transactionAllTags,
relatedPostings,
postingStripPrices,
postingApplyAliases,
postingApplyCommodityStyles,
postingStyleAmounts,
postingAddTags,
postingDate,
postingDate2,
postingDateOrDate2,
isPostingInDateSpan,
isPostingInDateSpan',
accountNamesFromPostings,
commentJoin,
commentAddTag,
commentAddTagUnspaced,
commentAddTagNextLine,
sumPostings,
showPosting,
showPostingLines,
postingAsLines,
postingsAsLines,
postingsAsLinesBeancount,
postingAsLinesBeancount,
showAccountName,
showAccountNameBeancount,
renderCommentLines,
showBalanceAssertion,
postingTransformAmount,
postingApplyValuation,
postingToCost,
postingAddInferredEquityPostings,
postingPriceDirectivesFromCost,
tests_Posting
)
where
import Data.Default (def)
import Data.Foldable (asum)
import Data.Function ((&))
import qualified Data.Map as M
import Data.Maybe (fromMaybe, isJust, mapMaybe)
import Data.List (foldl', sort, union)
import qualified Data.Set as S
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.Calendar (Day)
import Safe (maximumBound)
import Text.DocLayout (realLength)
import Text.Tabular.AsciiWide hiding (render)
import Hledger.Utils
import Hledger.Data.Types
import Hledger.Data.Amount
import Hledger.Data.AccountName
import Hledger.Data.Dates (nulldate, spanContainsDate)
import Hledger.Data.Valuation
instance HasAmounts BalanceAssertion where
styleAmounts :: Map CommoditySymbol AmountStyle
-> BalanceAssertion -> BalanceAssertion
styleAmounts Map CommoditySymbol AmountStyle
styles ba :: BalanceAssertion
ba@BalanceAssertion{Amount
baamount :: BalanceAssertion -> Amount
baamount :: Amount
baamount} = BalanceAssertion
ba{baamount :: Amount
baamount=Map CommoditySymbol AmountStyle -> Amount -> Amount
forall a. HasAmounts a => Map CommoditySymbol AmountStyle -> a -> a
styleAmounts Map CommoditySymbol AmountStyle
styles Amount
baamount}
instance HasAmounts Posting where
styleAmounts :: Map CommoditySymbol AmountStyle -> Posting -> Posting
styleAmounts Map CommoditySymbol AmountStyle
styles p :: Posting
p@Posting{MixedAmount
pamount :: Posting -> MixedAmount
pamount :: MixedAmount
pamount, Maybe BalanceAssertion
pbalanceassertion :: Posting -> Maybe BalanceAssertion
pbalanceassertion :: Maybe BalanceAssertion
pbalanceassertion} =
Posting
p{ pamount :: MixedAmount
pamount=Map CommoditySymbol AmountStyle -> MixedAmount -> MixedAmount
forall a. HasAmounts a => Map CommoditySymbol AmountStyle -> a -> a
styleAmounts Map CommoditySymbol AmountStyle
styles MixedAmount
pamount
,pbalanceassertion :: Maybe BalanceAssertion
pbalanceassertion=Map CommoditySymbol AmountStyle
-> Maybe BalanceAssertion -> Maybe BalanceAssertion
forall a. HasAmounts a => Map CommoditySymbol AmountStyle -> a -> a
styleAmounts Map CommoditySymbol AmountStyle
styles Maybe BalanceAssertion
pbalanceassertion
}
{-# DEPRECATED postingApplyCommodityStyles "please use styleAmounts instead" #-}
postingApplyCommodityStyles :: M.Map CommoditySymbol AmountStyle -> Posting -> Posting
postingApplyCommodityStyles :: Map CommoditySymbol AmountStyle -> Posting -> Posting
postingApplyCommodityStyles = Map CommoditySymbol AmountStyle -> Posting -> Posting
forall a. HasAmounts a => Map CommoditySymbol AmountStyle -> a -> a
styleAmounts
{-# DEPRECATED postingStyleAmounts "please use styleAmounts instead" #-}
postingStyleAmounts :: M.Map CommoditySymbol AmountStyle -> Posting -> Posting
postingStyleAmounts :: Map CommoditySymbol AmountStyle -> Posting -> Posting
postingStyleAmounts = Map CommoditySymbol AmountStyle -> Posting -> Posting
forall a. HasAmounts a => Map CommoditySymbol AmountStyle -> a -> a
styleAmounts
nullposting, posting :: Posting
nullposting :: Posting
nullposting = Posting :: Maybe Day
-> Maybe Day
-> Status
-> CommoditySymbol
-> MixedAmount
-> CommoditySymbol
-> PostingType
-> [Tag]
-> Maybe BalanceAssertion
-> Maybe Transaction
-> Maybe Posting
-> Posting
Posting
{pdate :: Maybe Day
pdate=Maybe Day
forall a. Maybe a
Nothing
,pdate2 :: Maybe Day
pdate2=Maybe Day
forall a. Maybe a
Nothing
,pstatus :: Status
pstatus=Status
Unmarked
,paccount :: CommoditySymbol
paccount=CommoditySymbol
""
,pamount :: MixedAmount
pamount=MixedAmount
nullmixedamt
,pcomment :: CommoditySymbol
pcomment=CommoditySymbol
""
,ptype :: PostingType
ptype=PostingType
RegularPosting
,ptags :: [Tag]
ptags=[]
,pbalanceassertion :: Maybe BalanceAssertion
pbalanceassertion=Maybe BalanceAssertion
forall a. Maybe a
Nothing
,ptransaction :: Maybe Transaction
ptransaction=Maybe Transaction
forall a. Maybe a
Nothing
,poriginal :: Maybe Posting
poriginal=Maybe Posting
forall a. Maybe a
Nothing
}
posting :: Posting
posting = Posting
nullposting
post :: AccountName -> Amount -> Posting
post :: CommoditySymbol -> Amount -> Posting
post CommoditySymbol
acc Amount
amt = Posting
posting {paccount :: CommoditySymbol
paccount=CommoditySymbol
acc, pamount :: MixedAmount
pamount=Amount -> MixedAmount
mixedAmount Amount
amt}
vpost :: AccountName -> Amount -> Posting
vpost :: CommoditySymbol -> Amount -> Posting
vpost CommoditySymbol
acc Amount
amt = (CommoditySymbol -> Amount -> Posting
post CommoditySymbol
acc Amount
amt){ptype :: PostingType
ptype=PostingType
VirtualPosting}
post' :: AccountName -> Amount -> Maybe BalanceAssertion -> Posting
post' :: CommoditySymbol -> Amount -> Maybe BalanceAssertion -> Posting
post' CommoditySymbol
acc Amount
amt Maybe BalanceAssertion
ass = Posting
posting {paccount :: CommoditySymbol
paccount=CommoditySymbol
acc, pamount :: MixedAmount
pamount=Amount -> MixedAmount
mixedAmount Amount
amt, pbalanceassertion :: Maybe BalanceAssertion
pbalanceassertion=Maybe BalanceAssertion
ass}
vpost' :: AccountName -> Amount -> Maybe BalanceAssertion -> Posting
vpost' :: CommoditySymbol -> Amount -> Maybe BalanceAssertion -> Posting
vpost' CommoditySymbol
acc Amount
amt Maybe BalanceAssertion
ass = (CommoditySymbol -> Amount -> Maybe BalanceAssertion -> Posting
post' CommoditySymbol
acc Amount
amt Maybe BalanceAssertion
ass){ptype :: PostingType
ptype=PostingType
VirtualPosting, pbalanceassertion :: Maybe BalanceAssertion
pbalanceassertion=Maybe BalanceAssertion
ass}
nullsourcepos :: (SourcePos, SourcePos)
nullsourcepos :: (SourcePos, SourcePos)
nullsourcepos = (FilePath -> Pos -> Pos -> SourcePos
SourcePos FilePath
"" (Int -> Pos
mkPos Int
1) (Int -> Pos
mkPos Int
1), FilePath -> Pos -> Pos -> SourcePos
SourcePos FilePath
"" (Int -> Pos
mkPos Int
2) (Int -> Pos
mkPos Int
1))
nullassertion :: BalanceAssertion
nullassertion :: BalanceAssertion
nullassertion = BalanceAssertion :: Amount -> Bool -> Bool -> SourcePos -> BalanceAssertion
BalanceAssertion
{baamount :: Amount
baamount=Amount
nullamt
,batotal :: Bool
batotal=Bool
False
,bainclusive :: Bool
bainclusive=Bool
False
,baposition :: SourcePos
baposition=FilePath -> SourcePos
initialPos FilePath
""
}
balassert :: Amount -> Maybe BalanceAssertion
balassert :: Amount -> Maybe BalanceAssertion
balassert Amount
amt = BalanceAssertion -> Maybe BalanceAssertion
forall a. a -> Maybe a
Just (BalanceAssertion -> Maybe BalanceAssertion)
-> BalanceAssertion -> Maybe BalanceAssertion
forall a b. (a -> b) -> a -> b
$ BalanceAssertion
nullassertion{baamount :: Amount
baamount=Amount
amt}
balassertTot :: Amount -> Maybe BalanceAssertion
balassertTot :: Amount -> Maybe BalanceAssertion
balassertTot Amount
amt = BalanceAssertion -> Maybe BalanceAssertion
forall a. a -> Maybe a
Just (BalanceAssertion -> Maybe BalanceAssertion)
-> BalanceAssertion -> Maybe BalanceAssertion
forall a b. (a -> b) -> a -> b
$ BalanceAssertion
nullassertion{baamount :: Amount
baamount=Amount
amt, batotal :: Bool
batotal=Bool
True}
balassertParInc :: Amount -> Maybe BalanceAssertion
balassertParInc :: Amount -> Maybe BalanceAssertion
balassertParInc Amount
amt = BalanceAssertion -> Maybe BalanceAssertion
forall a. a -> Maybe a
Just (BalanceAssertion -> Maybe BalanceAssertion)
-> BalanceAssertion -> Maybe BalanceAssertion
forall a b. (a -> b) -> a -> b
$ BalanceAssertion
nullassertion{baamount :: Amount
baamount=Amount
amt, bainclusive :: Bool
bainclusive=Bool
True}
balassertTotInc :: Amount -> Maybe BalanceAssertion
balassertTotInc :: Amount -> Maybe BalanceAssertion
balassertTotInc Amount
amt = BalanceAssertion -> Maybe BalanceAssertion
forall a. a -> Maybe a
Just (BalanceAssertion -> Maybe BalanceAssertion)
-> BalanceAssertion -> Maybe BalanceAssertion
forall a b. (a -> b) -> a -> b
$ BalanceAssertion
nullassertion{baamount :: Amount
baamount=Amount
amt, batotal :: Bool
batotal=Bool
True, bainclusive :: Bool
bainclusive=Bool
True}
showBalanceAssertion :: BalanceAssertion -> WideBuilder
showBalanceAssertion :: BalanceAssertion -> WideBuilder
showBalanceAssertion BalanceAssertion
ba =
Char -> WideBuilder
singleton Char
'=' WideBuilder -> WideBuilder -> WideBuilder
forall a. Semigroup a => a -> a -> a
<> WideBuilder
eq WideBuilder -> WideBuilder -> WideBuilder
forall a. Semigroup a => a -> a -> a
<> WideBuilder
ast WideBuilder -> WideBuilder -> WideBuilder
forall a. Semigroup a => a -> a -> a
<> Char -> WideBuilder
singleton Char
' ' WideBuilder -> WideBuilder -> WideBuilder
forall a. Semigroup a => a -> a -> a
<> AmountDisplayOpts -> Amount -> WideBuilder
showAmountB AmountDisplayOpts
forall a. Default a => a
def{displayZeroCommodity :: Bool
displayZeroCommodity=Bool
True} (BalanceAssertion -> Amount
baamount BalanceAssertion
ba)
where
eq :: WideBuilder
eq = if BalanceAssertion -> Bool
batotal BalanceAssertion
ba then Char -> WideBuilder
singleton Char
'=' else WideBuilder
forall a. Monoid a => a
mempty
ast :: WideBuilder
ast = if BalanceAssertion -> Bool
bainclusive BalanceAssertion
ba then Char -> WideBuilder
singleton Char
'*' else WideBuilder
forall a. Monoid a => a
mempty
singleton :: Char -> WideBuilder
singleton Char
c = Builder -> Int -> WideBuilder
WideBuilder (Char -> Builder
TB.singleton Char
c) Int
1
originalPosting :: Posting -> Posting
originalPosting :: Posting -> Posting
originalPosting Posting
p = Posting -> Maybe Posting -> Posting
forall a. a -> Maybe a -> a
fromMaybe Posting
p (Maybe Posting -> Posting) -> Maybe Posting -> Posting
forall a b. (a -> b) -> a -> b
$ Posting -> Maybe Posting
poriginal Posting
p
showPosting :: Posting -> String
showPosting :: Posting -> FilePath
showPosting Posting
p = CommoditySymbol -> FilePath
T.unpack (CommoditySymbol -> FilePath)
-> ([CommoditySymbol] -> CommoditySymbol)
-> [CommoditySymbol]
-> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [CommoditySymbol] -> CommoditySymbol
T.unlines ([CommoditySymbol] -> FilePath) -> [CommoditySymbol] -> FilePath
forall a b. (a -> b) -> a -> b
$ Bool -> [Posting] -> [CommoditySymbol]
postingsAsLines Bool
False [Posting
p]
showPostingLines :: Posting -> [Text]
showPostingLines :: Posting -> [CommoditySymbol]
showPostingLines Posting
p = ([CommoditySymbol], Int, Int) -> [CommoditySymbol]
forall a b c. (a, b, c) -> a
first3 (([CommoditySymbol], Int, Int) -> [CommoditySymbol])
-> ([CommoditySymbol], Int, Int) -> [CommoditySymbol]
forall a b. (a -> b) -> a -> b
$ Bool
-> Bool -> Int -> Int -> Posting -> ([CommoditySymbol], Int, Int)
postingAsLines Bool
False Bool
False Int
maxacctwidth Int
maxamtwidth Posting
p
where
linesWithWidths :: [([CommoditySymbol], Int, Int)]
linesWithWidths = (Posting -> ([CommoditySymbol], Int, Int))
-> [Posting] -> [([CommoditySymbol], Int, Int)]
forall a b. (a -> b) -> [a] -> [b]
map (Bool
-> Bool -> Int -> Int -> Posting -> ([CommoditySymbol], Int, Int)
postingAsLines Bool
False Bool
False Int
maxacctwidth Int
maxamtwidth) ([Posting] -> [([CommoditySymbol], Int, Int)])
-> (Maybe Transaction -> [Posting])
-> Maybe Transaction
-> [([CommoditySymbol], Int, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Posting]
-> (Transaction -> [Posting]) -> Maybe Transaction -> [Posting]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [Posting
p] Transaction -> [Posting]
tpostings (Maybe Transaction -> [([CommoditySymbol], Int, Int)])
-> Maybe Transaction -> [([CommoditySymbol], Int, Int)]
forall a b. (a -> b) -> a -> b
$ Posting -> Maybe Transaction
ptransaction Posting
p
maxacctwidth :: Int
maxacctwidth = Int -> [Int] -> Int
forall a. Ord a => a -> [a] -> a
maximumBound Int
0 ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (([CommoditySymbol], Int, Int) -> Int)
-> [([CommoditySymbol], Int, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ([CommoditySymbol], Int, Int) -> Int
forall a b c. (a, b, c) -> b
second3 [([CommoditySymbol], Int, Int)]
linesWithWidths
maxamtwidth :: Int
maxamtwidth = Int -> [Int] -> Int
forall a. Ord a => a -> [a] -> a
maximumBound Int
0 ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (([CommoditySymbol], Int, Int) -> Int)
-> [([CommoditySymbol], Int, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ([CommoditySymbol], Int, Int) -> Int
forall a b c. (a, b, c) -> c
third3 [([CommoditySymbol], Int, Int)]
linesWithWidths
postingsAsLines :: Bool -> [Posting] -> [Text]
postingsAsLines :: Bool -> [Posting] -> [CommoditySymbol]
postingsAsLines Bool
onelineamounts [Posting]
ps = (([CommoditySymbol], Int, Int) -> [CommoditySymbol])
-> [([CommoditySymbol], Int, Int)] -> [CommoditySymbol]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([CommoditySymbol], Int, Int) -> [CommoditySymbol]
forall a b c. (a, b, c) -> a
first3 [([CommoditySymbol], Int, Int)]
linesWithWidths
where
linesWithWidths :: [([CommoditySymbol], Int, Int)]
linesWithWidths = (Posting -> ([CommoditySymbol], Int, Int))
-> [Posting] -> [([CommoditySymbol], Int, Int)]
forall a b. (a -> b) -> [a] -> [b]
map (Bool
-> Bool -> Int -> Int -> Posting -> ([CommoditySymbol], Int, Int)
postingAsLines Bool
False Bool
onelineamounts Int
maxacctwidth Int
maxamtwidth) [Posting]
ps
maxacctwidth :: Int
maxacctwidth = Int -> [Int] -> Int
forall a. Ord a => a -> [a] -> a
maximumBound Int
0 ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (([CommoditySymbol], Int, Int) -> Int)
-> [([CommoditySymbol], Int, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ([CommoditySymbol], Int, Int) -> Int
forall a b c. (a, b, c) -> b
second3 [([CommoditySymbol], Int, Int)]
linesWithWidths
maxamtwidth :: Int
maxamtwidth = Int -> [Int] -> Int
forall a. Ord a => a -> [a] -> a
maximumBound Int
0 ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (([CommoditySymbol], Int, Int) -> Int)
-> [([CommoditySymbol], Int, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ([CommoditySymbol], Int, Int) -> Int
forall a b c. (a, b, c) -> c
third3 [([CommoditySymbol], Int, Int)]
linesWithWidths
postingAsLines :: Bool -> Bool -> Int -> Int -> Posting -> ([Text], Int, Int)
postingAsLines :: Bool
-> Bool -> Int -> Int -> Posting -> ([CommoditySymbol], Int, Int)
postingAsLines Bool
elideamount Bool
onelineamounts Int
acctwidth Int
amtwidth Posting
p =
(([CommoditySymbol] -> [CommoditySymbol])
-> [[CommoditySymbol]] -> [CommoditySymbol]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([CommoditySymbol] -> [CommoditySymbol] -> [CommoditySymbol]
forall a. [a] -> [a] -> [a]
++ [CommoditySymbol]
newlinecomments) [[CommoditySymbol]]
postingblocks, Int
thisacctwidth, Int
thisamtwidth)
where
postingblocks :: [[CommoditySymbol]]
postingblocks = [(CommoditySymbol -> CommoditySymbol)
-> [CommoditySymbol] -> [CommoditySymbol]
forall a b. (a -> b) -> [a] -> [b]
map CommoditySymbol -> CommoditySymbol
T.stripEnd ([CommoditySymbol] -> [CommoditySymbol])
-> (Text -> [CommoditySymbol]) -> Text -> [CommoditySymbol]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CommoditySymbol -> [CommoditySymbol]
T.lines (CommoditySymbol -> [CommoditySymbol])
-> (Text -> CommoditySymbol) -> Text -> [CommoditySymbol]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> CommoditySymbol
TL.toStrict (Text -> [CommoditySymbol]) -> Text -> [CommoditySymbol]
forall a b. (a -> b) -> a -> b
$
[Cell] -> Text
render [ Align -> CommoditySymbol -> Cell
textCell Align
BottomLeft CommoditySymbol
statusandaccount
, Align -> CommoditySymbol -> Cell
textCell Align
BottomLeft CommoditySymbol
" "
, Align -> [WideBuilder] -> Cell
Cell Align
BottomLeft [WideBuilder -> WideBuilder
pad WideBuilder
amt]
, Align -> [WideBuilder] -> Cell
Cell Align
BottomLeft [WideBuilder
assertion]
, Align -> CommoditySymbol -> Cell
textCell Align
BottomLeft CommoditySymbol
samelinecomment
]
| (WideBuilder
amt,WideBuilder
assertion) <- [(WideBuilder, WideBuilder)]
shownAmountsAssertions]
render :: [Cell] -> Text
render = TableOpts -> Header Cell -> Text
renderRow TableOpts
forall a. Default a => a
def{tableBorders :: Bool
tableBorders=Bool
False, borderSpaces :: Bool
borderSpaces=Bool
False} (Header Cell -> Text) -> ([Cell] -> Header Cell) -> [Cell] -> Text
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] -> 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
pad :: WideBuilder -> WideBuilder
pad WideBuilder
amt = Builder -> Int -> WideBuilder
WideBuilder (CommoditySymbol -> Builder
TB.fromText (CommoditySymbol -> Builder) -> CommoditySymbol -> Builder
forall a b. (a -> b) -> a -> b
$ Int -> CommoditySymbol -> CommoditySymbol
T.replicate Int
w CommoditySymbol
" ") Int
w WideBuilder -> WideBuilder -> WideBuilder
forall a. Semigroup a => a -> a -> a
<> WideBuilder
amt
where w :: Int
w = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
12 Int
amtwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
- WideBuilder -> Int
wbWidth WideBuilder
amt
pacctstr :: Posting -> CommoditySymbol
pacctstr Posting
p' = Maybe Int -> PostingType -> CommoditySymbol -> CommoditySymbol
showAccountName Maybe Int
forall a. Maybe a
Nothing (Posting -> PostingType
ptype Posting
p') (Posting -> CommoditySymbol
paccount Posting
p')
pstatusandacct :: Posting -> CommoditySymbol
pstatusandacct Posting
p' = Posting -> CommoditySymbol
pstatusprefix Posting
p' CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> Posting -> CommoditySymbol
pacctstr Posting
p'
pstatusprefix :: Posting -> CommoditySymbol
pstatusprefix Posting
p' = case Posting -> Status
pstatus Posting
p' of
Status
Unmarked -> CommoditySymbol
""
Status
s -> FilePath -> CommoditySymbol
T.pack (Status -> FilePath
forall a. Show a => a -> FilePath
show Status
s) CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> CommoditySymbol
" "
shownAmounts :: [WideBuilder]
shownAmounts
| Bool
elideamount = [WideBuilder
forall a. Monoid a => a
mempty]
| Bool
otherwise = AmountDisplayOpts -> MixedAmount -> [WideBuilder]
showMixedAmountLinesB AmountDisplayOpts
displayopts (MixedAmount -> [WideBuilder]) -> MixedAmount -> [WideBuilder]
forall a b. (a -> b) -> a -> b
$ Posting -> MixedAmount
pamount Posting
p
where displayopts :: AmountDisplayOpts
displayopts = AmountDisplayOpts
noColour{
displayZeroCommodity :: Bool
displayZeroCommodity=Bool
True, displayForceDecimalMark :: Bool
displayForceDecimalMark=Bool
True, displayOneLine :: Bool
displayOneLine=Bool
onelineamounts
}
thisamtwidth :: Int
thisamtwidth = Int -> [Int] -> Int
forall a. Ord a => a -> [a] -> a
maximumBound Int
0 ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (WideBuilder -> Int) -> [WideBuilder] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map WideBuilder -> Int
wbWidth [WideBuilder]
shownAmounts
shownAmountsAssertions :: [(WideBuilder, WideBuilder)]
shownAmountsAssertions = [WideBuilder] -> [WideBuilder] -> [(WideBuilder, WideBuilder)]
forall a b. [a] -> [b] -> [(a, b)]
zip [WideBuilder]
shownAmounts [WideBuilder]
shownAssertions
where
shownAssertions :: [WideBuilder]
shownAssertions = Int -> WideBuilder -> [WideBuilder]
forall a. Int -> a -> [a]
replicate ([WideBuilder] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [WideBuilder]
shownAmounts 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]
++ [WideBuilder
assertion]
where
assertion :: WideBuilder
assertion = WideBuilder
-> (BalanceAssertion -> WideBuilder)
-> Maybe BalanceAssertion
-> WideBuilder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe WideBuilder
forall a. Monoid a => a
mempty ((Builder -> Int -> WideBuilder
WideBuilder (Char -> Builder
TB.singleton Char
' ') Int
1 WideBuilder -> WideBuilder -> WideBuilder
forall a. Semigroup a => a -> a -> a
<>)(WideBuilder -> WideBuilder)
-> (BalanceAssertion -> WideBuilder)
-> BalanceAssertion
-> WideBuilder
forall b c a. (b -> c) -> (a -> b) -> a -> c
.BalanceAssertion -> WideBuilder
showBalanceAssertion) (Maybe BalanceAssertion -> WideBuilder)
-> Maybe BalanceAssertion -> WideBuilder
forall a b. (a -> b) -> a -> b
$ Posting -> Maybe BalanceAssertion
pbalanceassertion Posting
p
statusandaccount :: CommoditySymbol
statusandaccount = CommoditySymbol -> CommoditySymbol
lineIndent (CommoditySymbol -> CommoditySymbol)
-> (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol
-> CommoditySymbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Int
-> Maybe Int -> Bool -> Bool -> CommoditySymbol -> CommoditySymbol
fitText (Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
acctwidth) Maybe Int
forall a. Maybe a
Nothing Bool
False Bool
True (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol -> CommoditySymbol
forall a b. (a -> b) -> a -> b
$ Posting -> CommoditySymbol
pstatusandacct Posting
p
thisacctwidth :: Int
thisacctwidth = CommoditySymbol -> Int
forall a. HasChars a => a -> Int
realLength (CommoditySymbol -> Int) -> CommoditySymbol -> Int
forall a b. (a -> b) -> a -> b
$ Posting -> CommoditySymbol
pacctstr Posting
p
(CommoditySymbol
samelinecomment, [CommoditySymbol]
newlinecomments) =
case CommoditySymbol -> [CommoditySymbol]
renderCommentLines (Posting -> CommoditySymbol
pcomment Posting
p) of [] -> (CommoditySymbol
"",[])
CommoditySymbol
c:[CommoditySymbol]
cs -> (CommoditySymbol
c,[CommoditySymbol]
cs)
showAccountName :: Maybe Int -> PostingType -> AccountName -> Text
showAccountName :: Maybe Int -> PostingType -> CommoditySymbol -> CommoditySymbol
showAccountName Maybe Int
w = PostingType -> CommoditySymbol -> CommoditySymbol
fmt
where
fmt :: PostingType -> CommoditySymbol -> CommoditySymbol
fmt PostingType
RegularPosting = (CommoditySymbol -> CommoditySymbol)
-> (Int -> CommoditySymbol -> CommoditySymbol)
-> Maybe Int
-> CommoditySymbol
-> CommoditySymbol
forall b a. b -> (a -> b) -> Maybe a -> b
maybe CommoditySymbol -> CommoditySymbol
forall a. a -> a
id Int -> CommoditySymbol -> CommoditySymbol
T.take Maybe Int
w
fmt PostingType
VirtualPosting = CommoditySymbol
-> CommoditySymbol -> CommoditySymbol -> CommoditySymbol
wrap CommoditySymbol
"(" CommoditySymbol
")" (CommoditySymbol -> CommoditySymbol)
-> (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol
-> CommoditySymbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CommoditySymbol -> CommoditySymbol)
-> (Int -> CommoditySymbol -> CommoditySymbol)
-> Maybe Int
-> CommoditySymbol
-> CommoditySymbol
forall b a. b -> (a -> b) -> Maybe a -> b
maybe CommoditySymbol -> CommoditySymbol
forall a. a -> a
id (Int -> CommoditySymbol -> CommoditySymbol
T.takeEnd (Int -> CommoditySymbol -> CommoditySymbol)
-> (Int -> Int) -> Int -> CommoditySymbol -> CommoditySymbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> Int
forall a. Num a => a -> a -> a
subtract Int
2) Maybe Int
w
fmt PostingType
BalancedVirtualPosting = CommoditySymbol
-> CommoditySymbol -> CommoditySymbol -> CommoditySymbol
wrap CommoditySymbol
"[" CommoditySymbol
"]" (CommoditySymbol -> CommoditySymbol)
-> (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol
-> CommoditySymbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CommoditySymbol -> CommoditySymbol)
-> (Int -> CommoditySymbol -> CommoditySymbol)
-> Maybe Int
-> CommoditySymbol
-> CommoditySymbol
forall b a. b -> (a -> b) -> Maybe a -> b
maybe CommoditySymbol -> CommoditySymbol
forall a. a -> a
id (Int -> CommoditySymbol -> CommoditySymbol
T.takeEnd (Int -> CommoditySymbol -> CommoditySymbol)
-> (Int -> Int) -> Int -> CommoditySymbol -> CommoditySymbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> Int
forall a. Num a => a -> a -> a
subtract Int
2) Maybe Int
w
postingsAsLinesBeancount :: [Posting] -> [Text]
postingsAsLinesBeancount :: [Posting] -> [CommoditySymbol]
postingsAsLinesBeancount [Posting]
ps = (([CommoditySymbol], Int, Int) -> [CommoditySymbol])
-> [([CommoditySymbol], Int, Int)] -> [CommoditySymbol]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([CommoditySymbol], Int, Int) -> [CommoditySymbol]
forall a b c. (a, b, c) -> a
first3 [([CommoditySymbol], Int, Int)]
linesWithWidths
where
linesWithWidths :: [([CommoditySymbol], Int, Int)]
linesWithWidths = (Posting -> ([CommoditySymbol], Int, Int))
-> [Posting] -> [([CommoditySymbol], Int, Int)]
forall a b. (a -> b) -> [a] -> [b]
map (Bool -> Int -> Int -> Posting -> ([CommoditySymbol], Int, Int)
postingAsLinesBeancount Bool
False Int
maxacctwidth Int
maxamtwidth) [Posting]
ps
maxacctwidth :: Int
maxacctwidth = Int -> [Int] -> Int
forall a. Ord a => a -> [a] -> a
maximumBound Int
0 ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (([CommoditySymbol], Int, Int) -> Int)
-> [([CommoditySymbol], Int, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ([CommoditySymbol], Int, Int) -> Int
forall a b c. (a, b, c) -> b
second3 [([CommoditySymbol], Int, Int)]
linesWithWidths
maxamtwidth :: Int
maxamtwidth = Int -> [Int] -> Int
forall a. Ord a => a -> [a] -> a
maximumBound Int
0 ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (([CommoditySymbol], Int, Int) -> Int)
-> [([CommoditySymbol], Int, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ([CommoditySymbol], Int, Int) -> Int
forall a b c. (a, b, c) -> c
third3 [([CommoditySymbol], Int, Int)]
linesWithWidths
postingAsLinesBeancount :: Bool -> Int -> Int -> Posting -> ([Text], Int, Int)
postingAsLinesBeancount :: Bool -> Int -> Int -> Posting -> ([CommoditySymbol], Int, Int)
postingAsLinesBeancount Bool
elideamount Int
acctwidth Int
amtwidth Posting
p =
(([CommoditySymbol] -> [CommoditySymbol])
-> [[CommoditySymbol]] -> [CommoditySymbol]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([CommoditySymbol] -> [CommoditySymbol] -> [CommoditySymbol]
forall a. [a] -> [a] -> [a]
++ [CommoditySymbol]
newlinecomments) [[CommoditySymbol]]
postingblocks, Int
thisacctwidth, Int
thisamtwidth)
where
postingblocks :: [[CommoditySymbol]]
postingblocks = [(CommoditySymbol -> CommoditySymbol)
-> [CommoditySymbol] -> [CommoditySymbol]
forall a b. (a -> b) -> [a] -> [b]
map CommoditySymbol -> CommoditySymbol
T.stripEnd ([CommoditySymbol] -> [CommoditySymbol])
-> (Text -> [CommoditySymbol]) -> Text -> [CommoditySymbol]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CommoditySymbol -> [CommoditySymbol]
T.lines (CommoditySymbol -> [CommoditySymbol])
-> (Text -> CommoditySymbol) -> Text -> [CommoditySymbol]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> CommoditySymbol
TL.toStrict (Text -> [CommoditySymbol]) -> Text -> [CommoditySymbol]
forall a b. (a -> b) -> a -> b
$
[Cell] -> Text
render [ Align -> CommoditySymbol -> Cell
textCell Align
BottomLeft CommoditySymbol
statusandaccount
, Align -> CommoditySymbol -> Cell
textCell Align
BottomLeft CommoditySymbol
" "
, Align -> [WideBuilder] -> Cell
Cell Align
BottomLeft [WideBuilder -> WideBuilder
pad WideBuilder
amt]
, Align -> CommoditySymbol -> Cell
textCell Align
BottomLeft CommoditySymbol
samelinecomment
]
| (WideBuilder
amt,WideBuilder
_assertion) <- [(WideBuilder, WideBuilder)]
shownAmountsAssertions]
render :: [Cell] -> Text
render = TableOpts -> Header Cell -> Text
renderRow TableOpts
forall a. Default a => a
def{tableBorders :: Bool
tableBorders=Bool
False, borderSpaces :: Bool
borderSpaces=Bool
False} (Header Cell -> Text) -> ([Cell] -> Header Cell) -> [Cell] -> Text
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] -> 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
pad :: WideBuilder -> WideBuilder
pad WideBuilder
amt = Builder -> Int -> WideBuilder
WideBuilder (CommoditySymbol -> Builder
TB.fromText (CommoditySymbol -> Builder) -> CommoditySymbol -> Builder
forall a b. (a -> b) -> a -> b
$ Int -> CommoditySymbol -> CommoditySymbol
T.replicate Int
w CommoditySymbol
" ") Int
w WideBuilder -> WideBuilder -> WideBuilder
forall a. Semigroup a => a -> a -> a
<> WideBuilder
amt
where w :: Int
w = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
12 Int
amtwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
- WideBuilder -> Int
wbWidth WideBuilder
amt
pacct :: CommoditySymbol
pacct = Maybe Int -> CommoditySymbol -> CommoditySymbol
showAccountNameBeancount Maybe Int
forall a. Maybe a
Nothing (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol -> CommoditySymbol
forall a b. (a -> b) -> a -> b
$ Posting -> CommoditySymbol
paccount Posting
p
pstatusandacct :: Posting -> CommoditySymbol
pstatusandacct Posting
p' = if Posting -> Status
pstatus Posting
p' Status -> Status -> Bool
forall a. Eq a => a -> a -> Bool
== Status
Pending then CommoditySymbol
"! " else CommoditySymbol
"" CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> CommoditySymbol
pacct
shownAmounts :: [WideBuilder]
shownAmounts
| Bool
elideamount = [WideBuilder
forall a. Monoid a => a
mempty]
| Bool
otherwise = AmountDisplayOpts -> MixedAmount -> [WideBuilder]
showMixedAmountLinesB AmountDisplayOpts
displayopts MixedAmount
a'
where
displayopts :: AmountDisplayOpts
displayopts = AmountDisplayOpts
noColour{ displayZeroCommodity :: Bool
displayZeroCommodity=Bool
True, displayForceDecimalMark :: Bool
displayForceDecimalMark=Bool
True }
a' :: MixedAmount
a' = (Amount -> Amount) -> MixedAmount -> MixedAmount
mapMixedAmount Amount -> Amount
amountToBeancount (MixedAmount -> MixedAmount) -> MixedAmount -> MixedAmount
forall a b. (a -> b) -> a -> b
$ Posting -> MixedAmount
pamount Posting
p
thisamtwidth :: Int
thisamtwidth = Int -> [Int] -> Int
forall a. Ord a => a -> [a] -> a
maximumBound Int
0 ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (WideBuilder -> Int) -> [WideBuilder] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map WideBuilder -> Int
wbWidth [WideBuilder]
shownAmounts
shownAmountsAssertions :: [(WideBuilder, WideBuilder)]
shownAmountsAssertions = [WideBuilder] -> [WideBuilder] -> [(WideBuilder, WideBuilder)]
forall a b. [a] -> [b] -> [(a, b)]
zip [WideBuilder]
shownAmounts [WideBuilder]
shownAssertions
where
shownAssertions :: [WideBuilder]
shownAssertions = Int -> WideBuilder -> [WideBuilder]
forall a. Int -> a -> [a]
replicate ([WideBuilder] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [WideBuilder]
shownAmounts 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]
++ [WideBuilder
assertion]
where
assertion :: WideBuilder
assertion = WideBuilder
-> (BalanceAssertion -> WideBuilder)
-> Maybe BalanceAssertion
-> WideBuilder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe WideBuilder
forall a. Monoid a => a
mempty ((Builder -> Int -> WideBuilder
WideBuilder (Char -> Builder
TB.singleton Char
' ') Int
1 WideBuilder -> WideBuilder -> WideBuilder
forall a. Semigroup a => a -> a -> a
<>)(WideBuilder -> WideBuilder)
-> (BalanceAssertion -> WideBuilder)
-> BalanceAssertion
-> WideBuilder
forall b c a. (b -> c) -> (a -> b) -> a -> c
.BalanceAssertion -> WideBuilder
showBalanceAssertion) (Maybe BalanceAssertion -> WideBuilder)
-> Maybe BalanceAssertion -> WideBuilder
forall a b. (a -> b) -> a -> b
$ Posting -> Maybe BalanceAssertion
pbalanceassertion Posting
p
statusandaccount :: CommoditySymbol
statusandaccount = CommoditySymbol -> CommoditySymbol
lineIndent (CommoditySymbol -> CommoditySymbol)
-> (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol
-> CommoditySymbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Int
-> Maybe Int -> Bool -> Bool -> CommoditySymbol -> CommoditySymbol
fitText (Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
acctwidth) Maybe Int
forall a. Maybe a
Nothing Bool
False Bool
True (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol -> CommoditySymbol
forall a b. (a -> b) -> a -> b
$ Posting -> CommoditySymbol
pstatusandacct Posting
p
thisacctwidth :: Int
thisacctwidth = CommoditySymbol -> Int
forall a. HasChars a => a -> Int
realLength CommoditySymbol
pacct
(CommoditySymbol
samelinecomment, [CommoditySymbol]
newlinecomments) =
case CommoditySymbol -> [CommoditySymbol]
renderCommentLines (Posting -> CommoditySymbol
pcomment Posting
p) of [] -> (CommoditySymbol
"",[])
CommoditySymbol
c:[CommoditySymbol]
cs -> (CommoditySymbol
c,[CommoditySymbol]
cs)
type BeancountAmount = Amount
amountToBeancount :: Amount -> BeancountAmount
amountToBeancount :: Amount -> Amount
amountToBeancount a :: Amount
a@Amount{acommodity :: Amount -> CommoditySymbol
acommodity=CommoditySymbol
c,astyle :: Amount -> AmountStyle
astyle=AmountStyle
s,aprice :: Amount -> Maybe AmountPrice
aprice=Maybe AmountPrice
mp} = Amount
a{acommodity :: CommoditySymbol
acommodity=CommoditySymbol
c', astyle :: AmountStyle
astyle=AmountStyle
s', aprice :: Maybe AmountPrice
aprice=Maybe AmountPrice
mp'}
where
c' :: CommoditySymbol
c' = CommoditySymbol -> CommoditySymbol
T.toUpper (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol -> CommoditySymbol
forall a b. (a -> b) -> a -> b
$
CommoditySymbol
-> CommoditySymbol -> CommoditySymbol -> CommoditySymbol
T.replace CommoditySymbol
"$" CommoditySymbol
"USD" (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol -> CommoditySymbol
forall a b. (a -> b) -> a -> b
$
CommoditySymbol
-> CommoditySymbol -> CommoditySymbol -> CommoditySymbol
T.replace CommoditySymbol
"€" CommoditySymbol
"EUR" (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol -> CommoditySymbol
forall a b. (a -> b) -> a -> b
$
CommoditySymbol
-> CommoditySymbol -> CommoditySymbol -> CommoditySymbol
T.replace CommoditySymbol
"¥" CommoditySymbol
"JPY" (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol -> CommoditySymbol
forall a b. (a -> b) -> a -> b
$
CommoditySymbol
-> CommoditySymbol -> CommoditySymbol -> CommoditySymbol
T.replace CommoditySymbol
"£" CommoditySymbol
"GBP" (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol -> CommoditySymbol
forall a b. (a -> b) -> a -> b
$
CommoditySymbol
c
s' :: AmountStyle
s' = AmountStyle
s{ascommodityside :: Side
ascommodityside=Side
R, ascommodityspaced :: Bool
ascommodityspaced=Bool
True}
mp' :: Maybe AmountPrice
mp' = AmountPrice -> AmountPrice
costToBeancount (AmountPrice -> AmountPrice)
-> Maybe AmountPrice -> Maybe AmountPrice
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe AmountPrice
mp
where
costToBeancount :: AmountPrice -> AmountPrice
costToBeancount (TotalPrice Amount
amt) = Amount -> AmountPrice
TotalPrice (Amount -> AmountPrice) -> Amount -> AmountPrice
forall a b. (a -> b) -> a -> b
$ Amount -> Amount
amountToBeancount Amount
amt
costToBeancount (UnitPrice Amount
amt) = Amount -> AmountPrice
UnitPrice (Amount -> AmountPrice) -> Amount -> AmountPrice
forall a b. (a -> b) -> a -> b
$ Amount -> Amount
amountToBeancount Amount
amt
showAccountNameBeancount :: Maybe Int -> AccountName -> Text
showAccountNameBeancount :: Maybe Int -> CommoditySymbol -> CommoditySymbol
showAccountNameBeancount Maybe Int
w = (CommoditySymbol -> CommoditySymbol)
-> (Int -> CommoditySymbol -> CommoditySymbol)
-> Maybe Int
-> CommoditySymbol
-> CommoditySymbol
forall b a. b -> (a -> b) -> Maybe a -> b
maybe CommoditySymbol -> CommoditySymbol
forall a. a -> a
id Int -> CommoditySymbol -> CommoditySymbol
T.take Maybe Int
w (CommoditySymbol -> CommoditySymbol)
-> (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol
-> CommoditySymbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CommoditySymbol -> CommoditySymbol
accountNameToBeancount
renderCommentLines :: Text -> [Text]
CommoditySymbol
t =
case CommoditySymbol -> [CommoditySymbol]
T.lines CommoditySymbol
t of
[] -> []
[CommoditySymbol
l] -> [CommoditySymbol -> CommoditySymbol
commentSpace (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol -> CommoditySymbol
forall a b. (a -> b) -> a -> b
$ CommoditySymbol -> CommoditySymbol
comment CommoditySymbol
l]
(CommoditySymbol
"":[CommoditySymbol]
ls) -> CommoditySymbol
"" CommoditySymbol -> [CommoditySymbol] -> [CommoditySymbol]
forall a. a -> [a] -> [a]
: (CommoditySymbol -> CommoditySymbol)
-> [CommoditySymbol] -> [CommoditySymbol]
forall a b. (a -> b) -> [a] -> [b]
map (CommoditySymbol -> CommoditySymbol
lineIndent (CommoditySymbol -> CommoditySymbol)
-> (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol
-> CommoditySymbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CommoditySymbol -> CommoditySymbol
comment) [CommoditySymbol]
ls
(CommoditySymbol
l:[CommoditySymbol]
ls) -> CommoditySymbol -> CommoditySymbol
commentSpace (CommoditySymbol -> CommoditySymbol
comment CommoditySymbol
l) CommoditySymbol -> [CommoditySymbol] -> [CommoditySymbol]
forall a. a -> [a] -> [a]
: (CommoditySymbol -> CommoditySymbol)
-> [CommoditySymbol] -> [CommoditySymbol]
forall a b. (a -> b) -> [a] -> [b]
map (CommoditySymbol -> CommoditySymbol
lineIndent (CommoditySymbol -> CommoditySymbol)
-> (CommoditySymbol -> CommoditySymbol)
-> CommoditySymbol
-> CommoditySymbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CommoditySymbol -> CommoditySymbol
comment) [CommoditySymbol]
ls
where
comment :: CommoditySymbol -> CommoditySymbol
comment = (CommoditySymbol
"; "CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<>)
lineIndent :: Text -> Text
lineIndent :: CommoditySymbol -> CommoditySymbol
lineIndent = (CommoditySymbol
" "CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<>)
commentSpace :: Text -> Text
= (CommoditySymbol
" "CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<>)
isReal :: Posting -> Bool
isReal :: Posting -> Bool
isReal Posting
p = Posting -> PostingType
ptype Posting
p PostingType -> PostingType -> Bool
forall a. Eq a => a -> a -> Bool
== PostingType
RegularPosting
isVirtual :: Posting -> Bool
isVirtual :: Posting -> Bool
isVirtual Posting
p = Posting -> PostingType
ptype Posting
p PostingType -> PostingType -> Bool
forall a. Eq a => a -> a -> Bool
== PostingType
VirtualPosting
isBalancedVirtual :: Posting -> Bool
isBalancedVirtual :: Posting -> Bool
isBalancedVirtual Posting
p = Posting -> PostingType
ptype Posting
p PostingType -> PostingType -> Bool
forall a. Eq a => a -> a -> Bool
== PostingType
BalancedVirtualPosting
hasAmount :: Posting -> Bool
hasAmount :: Posting -> Bool
hasAmount = Bool -> Bool
not (Bool -> Bool) -> (Posting -> Bool) -> Posting -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MixedAmount -> Bool
isMissingMixedAmount (MixedAmount -> Bool)
-> (Posting -> MixedAmount) -> Posting -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Posting -> MixedAmount
pamount
hasBalanceAssignment :: Posting -> Bool
hasBalanceAssignment :: Posting -> Bool
hasBalanceAssignment Posting
p = Bool -> Bool
not (Posting -> Bool
hasAmount Posting
p) Bool -> Bool -> Bool
&& Maybe BalanceAssertion -> Bool
forall a. Maybe a -> Bool
isJust (Posting -> Maybe BalanceAssertion
pbalanceassertion Posting
p)
accountNamesFromPostings :: [Posting] -> [AccountName]
accountNamesFromPostings :: [Posting] -> [CommoditySymbol]
accountNamesFromPostings = Set CommoditySymbol -> [CommoditySymbol]
forall a. Set a -> [a]
S.toList (Set CommoditySymbol -> [CommoditySymbol])
-> ([Posting] -> Set CommoditySymbol)
-> [Posting]
-> [CommoditySymbol]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [CommoditySymbol] -> Set CommoditySymbol
forall a. Ord a => [a] -> Set a
S.fromList ([CommoditySymbol] -> Set CommoditySymbol)
-> ([Posting] -> [CommoditySymbol])
-> [Posting]
-> Set CommoditySymbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Posting -> CommoditySymbol) -> [Posting] -> [CommoditySymbol]
forall a b. (a -> b) -> [a] -> [b]
map Posting -> CommoditySymbol
paccount
sumPostings :: [Posting] -> MixedAmount
sumPostings :: [Posting] -> MixedAmount
sumPostings = (MixedAmount -> Posting -> MixedAmount)
-> MixedAmount -> [Posting] -> MixedAmount
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\MixedAmount
amt Posting
p -> MixedAmount -> MixedAmount -> MixedAmount
maPlus MixedAmount
amt (MixedAmount -> MixedAmount) -> MixedAmount -> MixedAmount
forall a b. (a -> b) -> a -> b
$ Posting -> MixedAmount
pamount Posting
p) MixedAmount
nullmixedamt
postingStripPrices :: Posting -> Posting
postingStripPrices :: Posting -> Posting
postingStripPrices = (MixedAmount -> MixedAmount) -> Posting -> Posting
postingTransformAmount MixedAmount -> MixedAmount
mixedAmountStripPrices
postingDate :: Posting -> Day
postingDate :: Posting -> Day
postingDate Posting
p = Day -> Maybe Day -> Day
forall a. a -> Maybe a -> a
fromMaybe Day
nulldate (Maybe Day -> Day) -> Maybe Day -> Day
forall a b. (a -> b) -> a -> b
$ [Maybe Day] -> Maybe Day
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum [Maybe Day]
dates
where dates :: [Maybe Day]
dates = [ Posting -> Maybe Day
pdate Posting
p, Transaction -> Day
tdate (Transaction -> Day) -> Maybe Transaction -> Maybe Day
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Posting -> Maybe Transaction
ptransaction Posting
p ]
postingDate2 :: Posting -> Day
postingDate2 :: Posting -> Day
postingDate2 Posting
p = Day -> Maybe Day -> Day
forall a. a -> Maybe a -> a
fromMaybe Day
nulldate (Maybe Day -> Day) -> Maybe Day -> Day
forall a b. (a -> b) -> a -> b
$ [Maybe Day] -> Maybe Day
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum [Maybe Day]
dates
where dates :: [Maybe Day]
dates = [ Posting -> Maybe Day
pdate2 Posting
p
, Transaction -> Maybe Day
tdate2 (Transaction -> Maybe Day) -> Maybe Transaction -> Maybe Day
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Posting -> Maybe Transaction
ptransaction Posting
p
, Posting -> Maybe Day
pdate Posting
p
, Transaction -> Day
tdate (Transaction -> Day) -> Maybe Transaction -> Maybe Day
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Posting -> Maybe Transaction
ptransaction Posting
p
]
postingDateOrDate2 :: WhichDate -> Posting -> Day
postingDateOrDate2 :: WhichDate -> Posting -> Day
postingDateOrDate2 WhichDate
PrimaryDate = Posting -> Day
postingDate
postingDateOrDate2 WhichDate
SecondaryDate = Posting -> Day
postingDate2
postingStatus :: Posting -> Status
postingStatus :: Posting -> Status
postingStatus Posting{pstatus :: Posting -> Status
pstatus=Status
s, ptransaction :: Posting -> Maybe Transaction
ptransaction=Maybe Transaction
mt} = case Status
s of
Status
Unmarked -> Status -> (Transaction -> Status) -> Maybe Transaction -> Status
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Status
Unmarked Transaction -> Status
tstatus Maybe Transaction
mt
Status
_ -> Status
s
postingAllTags :: Posting -> [Tag]
postingAllTags :: Posting -> [Tag]
postingAllTags Posting
p = Posting -> [Tag]
ptags Posting
p [Tag] -> [Tag] -> [Tag]
forall a. [a] -> [a] -> [a]
++ [Tag] -> (Transaction -> [Tag]) -> Maybe Transaction -> [Tag]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] Transaction -> [Tag]
ttags (Posting -> Maybe Transaction
ptransaction Posting
p)
transactionAllTags :: Transaction -> [Tag]
transactionAllTags :: Transaction -> [Tag]
transactionAllTags Transaction
t = Transaction -> [Tag]
ttags Transaction
t [Tag] -> [Tag] -> [Tag]
forall a. [a] -> [a] -> [a]
++ (Posting -> [Tag]) -> [Posting] -> [Tag]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Posting -> [Tag]
ptags (Transaction -> [Posting]
tpostings Transaction
t)
relatedPostings :: Posting -> [Posting]
relatedPostings :: Posting -> [Posting]
relatedPostings p :: Posting
p@Posting{ptransaction :: Posting -> Maybe Transaction
ptransaction=Just Transaction
t} = (Posting -> Bool) -> [Posting] -> [Posting]
forall a. (a -> Bool) -> [a] -> [a]
filter (Posting -> Posting -> Bool
forall a. Eq a => a -> a -> Bool
/= Posting
p) ([Posting] -> [Posting]) -> [Posting] -> [Posting]
forall a b. (a -> b) -> a -> b
$ Transaction -> [Posting]
tpostings Transaction
t
relatedPostings Posting
_ = []
isPostingInDateSpan :: DateSpan -> Posting -> Bool
isPostingInDateSpan :: DateSpan -> Posting -> Bool
isPostingInDateSpan = WhichDate -> DateSpan -> Posting -> Bool
isPostingInDateSpan' WhichDate
PrimaryDate
isPostingInDateSpan' :: WhichDate -> DateSpan -> Posting -> Bool
isPostingInDateSpan' :: WhichDate -> DateSpan -> Posting -> Bool
isPostingInDateSpan' WhichDate
PrimaryDate DateSpan
s = DateSpan -> Day -> Bool
spanContainsDate DateSpan
s (Day -> Bool) -> (Posting -> Day) -> Posting -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Posting -> Day
postingDate
isPostingInDateSpan' WhichDate
SecondaryDate DateSpan
s = DateSpan -> Day -> Bool
spanContainsDate DateSpan
s (Day -> Bool) -> (Posting -> Day) -> Posting -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Posting -> Day
postingDate2
isEmptyPosting :: Posting -> Bool
isEmptyPosting :: Posting -> Bool
isEmptyPosting = MixedAmount -> Bool
mixedAmountLooksZero (MixedAmount -> Bool)
-> (Posting -> MixedAmount) -> Posting -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Posting -> MixedAmount
pamount
postingApplyAliases :: [AccountAlias] -> Posting -> Either RegexError Posting
postingApplyAliases :: [AccountAlias] -> Posting -> Either FilePath Posting
postingApplyAliases [AccountAlias]
aliases p :: Posting
p@Posting{CommoditySymbol
paccount :: CommoditySymbol
paccount :: Posting -> CommoditySymbol
paccount} =
case [AccountAlias]
-> CommoditySymbol -> Either FilePath CommoditySymbol
accountNameApplyAliases [AccountAlias]
aliases CommoditySymbol
paccount of
Right CommoditySymbol
a -> Posting -> Either FilePath Posting
forall a b. b -> Either a b
Right Posting
p{paccount :: CommoditySymbol
paccount=CommoditySymbol
a}
Left FilePath
e -> FilePath -> Either FilePath Posting
forall a b. a -> Either a b
Left FilePath
err
where
err :: FilePath
err = FilePath
"problem while applying account aliases:\n" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ [AccountAlias] -> FilePath
forall a. Show a => a -> FilePath
pshow [AccountAlias]
aliases
FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\n to account name: "FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++CommoditySymbol -> FilePath
T.unpack CommoditySymbol
paccountFilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"\n "FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
e
postingAddTags :: Posting -> [Tag] -> Posting
postingAddTags :: Posting -> [Tag] -> Posting
postingAddTags p :: Posting
p@Posting{[Tag]
ptags :: [Tag]
ptags :: Posting -> [Tag]
ptags} [Tag]
tags = Posting
p{ptags :: [Tag]
ptags=[Tag]
ptags [Tag] -> [Tag] -> [Tag]
forall a. Eq a => [a] -> [a] -> [a]
`union` [Tag]
tags}
postingApplyValuation :: PriceOracle -> M.Map CommoditySymbol AmountStyle -> Day -> Day -> ValuationType -> Posting -> Posting
postingApplyValuation :: PriceOracle
-> Map CommoditySymbol AmountStyle
-> Day
-> Day
-> ValuationType
-> Posting
-> Posting
postingApplyValuation PriceOracle
priceoracle Map CommoditySymbol AmountStyle
styles Day
periodlast Day
today ValuationType
v Posting
p =
(MixedAmount -> MixedAmount) -> Posting -> Posting
postingTransformAmount (PriceOracle
-> Map CommoditySymbol AmountStyle
-> Day
-> Day
-> Day
-> ValuationType
-> MixedAmount
-> MixedAmount
mixedAmountApplyValuation PriceOracle
priceoracle Map CommoditySymbol AmountStyle
styles Day
periodlast Day
today (Posting -> Day
postingDate Posting
p) ValuationType
v) Posting
p
postingToCost :: ConversionOp -> Posting -> Maybe Posting
postingToCost :: ConversionOp -> Posting -> Maybe Posting
postingToCost ConversionOp
NoConversionOp Posting
p = Posting -> Maybe Posting
forall a. a -> Maybe a
Just Posting
p
postingToCost ConversionOp
ToCost Posting
p
| CommoditySymbol
"_conversion-matched" CommoditySymbol -> [CommoditySymbol] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (Tag -> CommoditySymbol) -> [Tag] -> [CommoditySymbol]
forall a b. (a -> b) -> [a] -> [b]
map Tag -> CommoditySymbol
forall a b. (a, b) -> a
fst (Posting -> [Tag]
ptags Posting
p) Bool -> Bool -> Bool
&& Bool
nocosts = Maybe Posting
forall a. Maybe a
Nothing
| Bool
otherwise = Posting -> Maybe Posting
forall a. a -> Maybe a
Just (Posting -> Maybe Posting) -> Posting -> Maybe Posting
forall a b. (a -> b) -> a -> b
$ (MixedAmount -> MixedAmount) -> Posting -> Posting
postingTransformAmount MixedAmount -> MixedAmount
mixedAmountCost Posting
p
where
nocosts :: Bool
nocosts = (Bool -> Bool
not (Bool -> Bool) -> (MixedAmount -> Bool) -> MixedAmount -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Amount -> Bool) -> [Amount] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Maybe AmountPrice -> Bool
forall a. Maybe a -> Bool
isJust (Maybe AmountPrice -> Bool)
-> (Amount -> Maybe AmountPrice) -> Amount -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Amount -> Maybe AmountPrice
aprice) ([Amount] -> Bool)
-> (MixedAmount -> [Amount]) -> MixedAmount -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MixedAmount -> [Amount]
amountsRaw) (MixedAmount -> Bool) -> MixedAmount -> Bool
forall a b. (a -> b) -> a -> b
$ Posting -> MixedAmount
pamount Posting
p
postingAddInferredEquityPostings :: Bool -> Text -> Posting -> [Posting]
postingAddInferredEquityPostings :: Bool -> CommoditySymbol -> Posting -> [Posting]
postingAddInferredEquityPostings Bool
verbosetags CommoditySymbol
equityAcct Posting
p
| CommoditySymbol
"_price-matched" CommoditySymbol -> [CommoditySymbol] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (Tag -> CommoditySymbol) -> [Tag] -> [CommoditySymbol]
forall a b. (a -> b) -> [a] -> [b]
map Tag -> CommoditySymbol
forall a b. (a, b) -> a
fst (Posting -> [Tag]
ptags Posting
p) = [Posting
p]
| Bool
otherwise = Posting
taggedPosting Posting -> [Posting] -> [Posting]
forall a. a -> [a] -> [a]
: (Amount -> [Posting]) -> [Amount] -> [Posting]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Amount -> [Posting]
conversionPostings [Amount]
priceAmounts
where
taggedPosting :: Posting
taggedPosting
| [Amount] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Amount]
priceAmounts = Posting
p
| Bool
otherwise = Posting
p{ ptags :: [Tag]
ptags = (CommoditySymbol
"_price-matched",CommoditySymbol
"") Tag -> [Tag] -> [Tag]
forall a. a -> [a] -> [a]
: Posting -> [Tag]
ptags Posting
p }
conversionPostings :: Amount -> [Posting]
conversionPostings Amount
amt = case Amount -> Maybe AmountPrice
aprice Amount
amt of
Maybe AmountPrice
Nothing -> []
Just AmountPrice
_ -> [ Posting
cp{ paccount :: CommoditySymbol
paccount = CommoditySymbol
accountPrefix CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> CommoditySymbol
amtCommodity
, pamount :: MixedAmount
pamount = Amount -> MixedAmount
mixedAmount (Amount -> MixedAmount)
-> (Amount -> Amount) -> Amount -> MixedAmount
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Amount -> Amount
forall a. Num a => a -> a
negate (Amount -> MixedAmount) -> Amount -> MixedAmount
forall a b. (a -> b) -> a -> b
$ Amount -> Amount
amountStripCost Amount
amt
}
, Posting
cp{ paccount :: CommoditySymbol
paccount = CommoditySymbol
accountPrefix CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> CommoditySymbol
costCommodity
, pamount :: MixedAmount
pamount = Amount -> MixedAmount
mixedAmount Amount
cost
}
]
where
cost :: Amount
cost = Amount -> Amount
amountCost Amount
amt
amtCommodity :: CommoditySymbol
amtCommodity = Amount -> CommoditySymbol
commodity Amount
amt
costCommodity :: CommoditySymbol
costCommodity = Amount -> CommoditySymbol
commodity Amount
cost
cp :: Posting
cp = Posting
p{ pcomment :: CommoditySymbol
pcomment = Posting -> CommoditySymbol
pcomment Posting
p CommoditySymbol
-> (CommoditySymbol -> CommoditySymbol) -> CommoditySymbol
forall a b. a -> (a -> b) -> b
& (if Bool
verbosetags then (CommoditySymbol -> Tag -> CommoditySymbol
`commentAddTag` (CommoditySymbol
"generated-posting",CommoditySymbol
"conversion")) else CommoditySymbol -> CommoditySymbol
forall a. a -> a
id)
, ptags :: [Tag]
ptags =
(CommoditySymbol
"_conversion-matched",CommoditySymbol
"") Tag -> [Tag] -> [Tag]
forall a. a -> [a] -> [a]
:
(CommoditySymbol
"_generated-posting",CommoditySymbol
"conversion") Tag -> [Tag] -> [Tag]
forall a. a -> [a] -> [a]
:
(if Bool
verbosetags then [(CommoditySymbol
"generated-posting", CommoditySymbol
"conversion")] else [])
, pbalanceassertion :: Maybe BalanceAssertion
pbalanceassertion = Maybe BalanceAssertion
forall a. Maybe a
Nothing
, poriginal :: Maybe Posting
poriginal = Maybe Posting
forall a. Maybe a
Nothing
}
accountPrefix :: CommoditySymbol
accountPrefix = [CommoditySymbol] -> CommoditySymbol
forall a. Monoid a => [a] -> a
mconcat [ CommoditySymbol
equityAcct, CommoditySymbol
":", CommoditySymbol -> [CommoditySymbol] -> CommoditySymbol
T.intercalate CommoditySymbol
"-" ([CommoditySymbol] -> CommoditySymbol)
-> [CommoditySymbol] -> CommoditySymbol
forall a b. (a -> b) -> a -> b
$ [CommoditySymbol] -> [CommoditySymbol]
forall a. Ord a => [a] -> [a]
sort [CommoditySymbol
amtCommodity, CommoditySymbol
costCommodity], CommoditySymbol
":"]
commodity :: Amount -> CommoditySymbol
commodity = [CommoditySymbol] -> CommoditySymbol
T.unwords ([CommoditySymbol] -> CommoditySymbol)
-> (Amount -> [CommoditySymbol]) -> Amount -> CommoditySymbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CommoditySymbol -> Bool) -> [CommoditySymbol] -> [CommoditySymbol]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> (CommoditySymbol -> Bool) -> CommoditySymbol -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CommoditySymbol -> Bool
T.null) ([CommoditySymbol] -> [CommoditySymbol])
-> (Amount -> [CommoditySymbol]) -> Amount -> [CommoditySymbol]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CommoditySymbol -> [CommoditySymbol]
T.words (CommoditySymbol -> [CommoditySymbol])
-> (Amount -> CommoditySymbol) -> Amount -> [CommoditySymbol]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Amount -> CommoditySymbol
acommodity
priceAmounts :: [Amount]
priceAmounts = (Amount -> Bool) -> [Amount] -> [Amount]
forall a. (a -> Bool) -> [a] -> [a]
filter (Maybe AmountPrice -> Bool
forall a. Maybe a -> Bool
isJust (Maybe AmountPrice -> Bool)
-> (Amount -> Maybe AmountPrice) -> Amount -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Amount -> Maybe AmountPrice
aprice) ([Amount] -> [Amount])
-> (MixedAmount -> [Amount]) -> MixedAmount -> [Amount]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MixedAmount -> [Amount]
amountsRaw (MixedAmount -> [Amount]) -> MixedAmount -> [Amount]
forall a b. (a -> b) -> a -> b
$ Posting -> MixedAmount
pamount Posting
p
postingPriceDirectivesFromCost :: Posting -> [PriceDirective]
postingPriceDirectivesFromCost :: Posting -> [PriceDirective]
postingPriceDirectivesFromCost p :: Posting
p@Posting{MixedAmount
pamount :: MixedAmount
pamount :: Posting -> MixedAmount
pamount} =
(Amount -> Maybe PriceDirective) -> [Amount] -> [PriceDirective]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (Day -> Amount -> Maybe PriceDirective
amountPriceDirectiveFromCost (Day -> Amount -> Maybe PriceDirective)
-> Day -> Amount -> Maybe PriceDirective
forall a b. (a -> b) -> a -> b
$ Posting -> Day
postingDate Posting
p) ([Amount] -> [PriceDirective]) -> [Amount] -> [PriceDirective]
forall a b. (a -> b) -> a -> b
$ MixedAmount -> [Amount]
amountsRaw MixedAmount
pamount
postingTransformAmount :: (MixedAmount -> MixedAmount) -> Posting -> Posting
postingTransformAmount :: (MixedAmount -> MixedAmount) -> Posting -> Posting
postingTransformAmount MixedAmount -> MixedAmount
f p :: Posting
p@Posting{pamount :: Posting -> MixedAmount
pamount=MixedAmount
a} = Posting
p{pamount :: MixedAmount
pamount=MixedAmount -> MixedAmount
f MixedAmount
a}
commentJoin :: Text -> Text -> Text
CommoditySymbol
c1 CommoditySymbol
c2
| CommoditySymbol -> Bool
T.null CommoditySymbol
c1 = CommoditySymbol
c2
| CommoditySymbol -> Bool
T.null CommoditySymbol
c2 = CommoditySymbol
c1
| Bool
otherwise = CommoditySymbol
c1 CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> CommoditySymbol
", " CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> CommoditySymbol
c2
commentAddTag :: Text -> Tag -> Text
CommoditySymbol
c (CommoditySymbol
t,CommoditySymbol
v)
| CommoditySymbol -> Bool
T.null CommoditySymbol
c' = CommoditySymbol
tag
| Bool
otherwise = CommoditySymbol
c' CommoditySymbol -> CommoditySymbol -> CommoditySymbol
`commentJoin` CommoditySymbol
tag
where
c' :: CommoditySymbol
c' = CommoditySymbol -> CommoditySymbol
T.stripEnd CommoditySymbol
c
tag :: CommoditySymbol
tag = CommoditySymbol
t CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> CommoditySymbol
": " CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> CommoditySymbol
v
commentAddTagUnspaced :: Text -> Tag -> Text
CommoditySymbol
c (CommoditySymbol
t,CommoditySymbol
v)
| CommoditySymbol -> Bool
T.null CommoditySymbol
c' = CommoditySymbol
tag
| Bool
otherwise = CommoditySymbol
c' CommoditySymbol -> CommoditySymbol -> CommoditySymbol
`commentJoin` CommoditySymbol
tag
where
c' :: CommoditySymbol
c' = CommoditySymbol -> CommoditySymbol
T.stripEnd CommoditySymbol
c
tag :: CommoditySymbol
tag = CommoditySymbol
t CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> CommoditySymbol
":" CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> CommoditySymbol
v
commentAddTagNextLine :: Text -> Tag -> Text
CommoditySymbol
cmt (CommoditySymbol
t,CommoditySymbol
v) =
CommoditySymbol
cmt CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> (if CommoditySymbol
"\n" CommoditySymbol -> CommoditySymbol -> Bool
`T.isSuffixOf` CommoditySymbol
cmt then CommoditySymbol
"" else CommoditySymbol
"\n") CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> CommoditySymbol
t CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> CommoditySymbol
": " CommoditySymbol -> CommoditySymbol -> CommoditySymbol
forall a. Semigroup a => a -> a -> a
<> CommoditySymbol
v
tests_Posting :: TestTree
tests_Posting = FilePath -> [TestTree] -> TestTree
testGroup FilePath
"Posting" [
FilePath -> Assertion -> TestTree
testCase FilePath
"accountNamePostingType" (Assertion -> TestTree) -> Assertion -> TestTree
forall a b. (a -> b) -> a -> b
$ do
CommoditySymbol -> PostingType
accountNamePostingType CommoditySymbol
"a" PostingType -> PostingType -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= PostingType
RegularPosting
CommoditySymbol -> PostingType
accountNamePostingType CommoditySymbol
"(a)" PostingType -> PostingType -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= PostingType
VirtualPosting
CommoditySymbol -> PostingType
accountNamePostingType CommoditySymbol
"[a]" PostingType -> PostingType -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= PostingType
BalancedVirtualPosting
,FilePath -> Assertion -> TestTree
testCase FilePath
"accountNameWithoutPostingType" (Assertion -> TestTree) -> Assertion -> TestTree
forall a b. (a -> b) -> a -> b
$ do
CommoditySymbol -> CommoditySymbol
accountNameWithoutPostingType CommoditySymbol
"(a)" CommoditySymbol -> CommoditySymbol -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= CommoditySymbol
"a"
,FilePath -> Assertion -> TestTree
testCase FilePath
"accountNameWithPostingType" (Assertion -> TestTree) -> Assertion -> TestTree
forall a b. (a -> b) -> a -> b
$ do
PostingType -> CommoditySymbol -> CommoditySymbol
accountNameWithPostingType PostingType
VirtualPosting CommoditySymbol
"[a]" CommoditySymbol -> CommoditySymbol -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= CommoditySymbol
"(a)"
,FilePath -> Assertion -> TestTree
testCase FilePath
"joinAccountNames" (Assertion -> TestTree) -> Assertion -> TestTree
forall a b. (a -> b) -> a -> b
$ do
CommoditySymbol
"a" CommoditySymbol -> CommoditySymbol -> CommoditySymbol
`joinAccountNames` CommoditySymbol
"b:c" CommoditySymbol -> CommoditySymbol -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= CommoditySymbol
"a:b:c"
CommoditySymbol
"a" CommoditySymbol -> CommoditySymbol -> CommoditySymbol
`joinAccountNames` CommoditySymbol
"(b:c)" CommoditySymbol -> CommoditySymbol -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= CommoditySymbol
"(a:b:c)"
CommoditySymbol
"[a]" CommoditySymbol -> CommoditySymbol -> CommoditySymbol
`joinAccountNames` CommoditySymbol
"(b:c)" CommoditySymbol -> CommoditySymbol -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= CommoditySymbol
"[a:b:c]"
CommoditySymbol
"" CommoditySymbol -> CommoditySymbol -> CommoditySymbol
`joinAccountNames` CommoditySymbol
"a" CommoditySymbol -> CommoditySymbol -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= CommoditySymbol
"a"
,FilePath -> Assertion -> TestTree
testCase FilePath
"concatAccountNames" (Assertion -> TestTree) -> Assertion -> TestTree
forall a b. (a -> b) -> a -> b
$ do
[CommoditySymbol] -> CommoditySymbol
concatAccountNames [] CommoditySymbol -> CommoditySymbol -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= CommoditySymbol
""
[CommoditySymbol] -> CommoditySymbol
concatAccountNames [CommoditySymbol
"a",CommoditySymbol
"(b)",CommoditySymbol
"[c:d]"] CommoditySymbol -> CommoditySymbol -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= CommoditySymbol
"(a:b:c:d)"
,FilePath -> Assertion -> TestTree
testCase FilePath
"commentAddTag" (Assertion -> TestTree) -> Assertion -> TestTree
forall a b. (a -> b) -> a -> b
$ do
CommoditySymbol -> Tag -> CommoditySymbol
commentAddTag CommoditySymbol
"" (CommoditySymbol
"a",CommoditySymbol
"") CommoditySymbol -> CommoditySymbol -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= CommoditySymbol
"a: "
CommoditySymbol -> Tag -> CommoditySymbol
commentAddTag CommoditySymbol
"[1/2]" (CommoditySymbol
"a",CommoditySymbol
"") CommoditySymbol -> CommoditySymbol -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= CommoditySymbol
"[1/2], a: "
,FilePath -> Assertion -> TestTree
testCase FilePath
"commentAddTagNextLine" (Assertion -> TestTree) -> Assertion -> TestTree
forall a b. (a -> b) -> a -> b
$ do
CommoditySymbol -> Tag -> CommoditySymbol
commentAddTagNextLine CommoditySymbol
"" (CommoditySymbol
"a",CommoditySymbol
"") CommoditySymbol -> CommoditySymbol -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= CommoditySymbol
"\na: "
CommoditySymbol -> Tag -> CommoditySymbol
commentAddTagNextLine CommoditySymbol
"[1/2]" (CommoditySymbol
"a",CommoditySymbol
"") CommoditySymbol -> CommoditySymbol -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= CommoditySymbol
"[1/2]\na: "
]