journal: also support lot dates ([DATE])

This commit is contained in:
Simon Michael 2020-04-08 19:55:55 -07:00
parent fedde7fab1
commit f4a1a31712
3 changed files with 37 additions and 23 deletions

View File

@ -137,6 +137,7 @@ import Text.Megaparsec
import Text.Megaparsec.Char import Text.Megaparsec.Char
import Text.Megaparsec.Char.Lexer (decimal) import Text.Megaparsec.Char.Lexer (decimal)
import Text.Megaparsec.Custom import Text.Megaparsec.Custom
import Control.Applicative.Permutations
import Hledger.Data import Hledger.Data
import Hledger.Utils import Hledger.Utils
@ -610,11 +611,11 @@ spaceandamountormissingp =
amountp :: JournalParser m Amount amountp :: JournalParser m Amount
amountp = label "amount" $ do amountp = label "amount" $ do
let spaces = lift $ skipMany spacenonewline let spaces = lift $ skipMany spacenonewline
amount <- amountwithoutpricep amount <- amountwithoutpricep <* spaces
spaces (mprice, _elotprice, _elotdate) <- runPermutation $
_elotprice <- optional $ lotpricep <* spaces (,,) <$> toPermutationWithDefault Nothing (Just <$> priceamountp <* spaces)
mprice <- optional $ priceamountp <* spaces <*> toPermutationWithDefault Nothing (Just <$> lotpricep <* spaces)
_elotprice <- optional $ lotpricep <*> toPermutationWithDefault Nothing (Just <$> lotdatep <* spaces)
pure $ amount { aprice = mprice } pure $ amount { aprice = mprice }
-- XXX Just like amountp but don't allow lot prices. Needed for balanceassertionp. -- XXX Just like amountp but don't allow lot prices. Needed for balanceassertionp.
@ -761,21 +762,33 @@ balanceassertionp = do
, baposition = sourcepos , baposition = sourcepos
} }
-- Parse a Ledger-style fixed {=PRICE} or non-fixed {PRICE} lot price, -- Parse a Ledger-style fixed {=UNITPRICE} or non-fixed {UNITPRICE}
-- as a Left or Right Amount respectively. -- or fixed {{=TOTALPRICE}} or non-fixed {{TOTALPRICE}} lot price,
-- and ignore it.
-- https://www.ledger-cli.org/3.0/doc/ledger3.html#Fixing-Lot-Prices . -- https://www.ledger-cli.org/3.0/doc/ledger3.html#Fixing-Lot-Prices .
lotpricep :: JournalParser m (Either Amount Amount) lotpricep :: JournalParser m ()
lotpricep = (do lotpricep = label "ledger-style lot price" $ do
char '{' char '{'
doublebrace <- option False $ char '{' >> pure True doublebrace <- option False $ char '{' >> pure True
fixed <- fmap isJust $ optional $ lift (skipMany spacenonewline) >> char '=' _fixed <- fmap isJust $ optional $ lift (skipMany spacenonewline) >> char '='
lift (skipMany spacenonewline) lift (skipMany spacenonewline)
a <- amountwithoutpricep _a <- amountwithoutpricep
lift (skipMany spacenonewline) lift (skipMany spacenonewline)
char '}' char '}'
when (doublebrace) $ void $ char '}' when (doublebrace) $ void $ char '}'
return $ (if fixed then Left else Right) a return ()
) <?> "ledger-style lot price or fixed lot price"
-- Parse a Ledger-style lot date [DATE], and ignore it.
-- https://www.ledger-cli.org/3.0/doc/ledger3.html#Fixing-Lot-Prices .
lotdatep :: JournalParser m ()
lotdatep = (do
char '['
lift (skipMany spacenonewline)
_d <- datep
lift (skipMany spacenonewline)
char ']'
return ()
) <?> "ledger-style lot date"
-- | Parse a string representation of a number for its value and display -- | Parse a string representation of a number for its value and display
-- attributes. -- attributes.

View File

@ -862,6 +862,9 @@ tests_JournalReader = tests "JournalReader" [
,test "lot price before transaction price" $ assertParse (postingp Nothing) " a 1A {1B} @ 1B\n" ,test "lot price before transaction price" $ assertParse (postingp Nothing) " a 1A {1B} @ 1B\n"
,test "lot price after transaction price" $ assertParse (postingp Nothing) " a 1A @ 1B {1B}\n" ,test "lot price after transaction price" $ assertParse (postingp Nothing) " a 1A @ 1B {1B}\n"
,test "lot price after balance assertion not allowed" $ assertParseError (postingp Nothing) " a 1A @ 1B = 1A {1B}\n" "unexpected '{'" ,test "lot price after balance assertion not allowed" $ assertParseError (postingp Nothing) " a 1A @ 1B = 1A {1B}\n" "unexpected '{'"
,test "only lot date" $ assertParse (postingp Nothing) " a 1A [2000-01-01]\n"
,test "transaction price, lot price, lot date" $ assertParse (postingp Nothing) " a 1A @ 1B {1B} [2000-01-01]\n"
,test "lot date, lot price, transaction price" $ assertParse (postingp Nothing) " a 1A [2000-01-01] {1B} @ 1B\n"
,test "balance assertion over entire contents of account" $ assertParse (postingp Nothing) " a $1 == $1\n" ,test "balance assertion over entire contents of account" $ assertParse (postingp Nothing) " a $1 == $1\n"
] ]

View File

@ -579,18 +579,16 @@ $ hledger bal -N --flat -B
€100 assets:euros €100 assets:euros
``` ```
## Lot Prices ## Lot Prices and Lot Dates
Ledger allows another kind of price, Ledger allows another kind of price,
[lot price](http://ledger-cli.org/3.0/doc/ledger3.html#Fixing-Lot-Prices), [lot price](http://ledger-cli.org/3.0/doc/ledger3.html#Fixing-Lot-Prices)
to be specified in curly braces (four variants: `{UNITPRICE}`, `{{TOTALPRICE}}`, `{=FIXEDUNITPRICE}`, `{{=FIXEDTOTALPRICE}}`),
(three variants: `{UNITPRICE}`, `{{TOTALPRICE}}`, `{=FIXEDUNITPRICE}`). and/or a lot date (`[DATE]`) to be specified.
This is normally used to select a lot when selling investments. These are normally used to select a lot when selling investments.
hledger will parse these, for compatibility with Ledger journals, but hledger will parse these, for compatibility with Ledger journals, but currently ignores them.
currently ignores them. A [transaction price](#transaction-prices), lot price and/or lot date may appear in any order,
They may appear after the posting amount, before or after the after the posting amount and before the balance assertion if any.
[transaction price](#transaction-prices) if any, and before the
balance assertion if any.
## Balance Assertions ## Balance Assertions