CsvReader: simplify '-' signs if there exist more than one (#548)

It prevents hledger to crash later, as it fails to read
amount strings containing more than one '-'

Fix #524
This commit is contained in:
Nicolas Wavrant 2017-05-14 02:34:33 +02:00 committed by Simon Michael
parent a4293dca6e
commit 309d1ccd59
2 changed files with 27 additions and 1 deletions

View File

@ -35,6 +35,7 @@ import Control.Monad.Except
import Control.Monad.State.Strict (StateT, get, modify', evalStateT)
-- import Test.HUnit
import Data.Char (toLower, isDigit, isSpace)
import Data.List (findIndices)
import Data.List.Compat
import Data.Maybe
import Data.Ord
@ -641,7 +642,7 @@ transactionFromCsvRecord sourcepos rules record = t
comment = maybe "" render $ mfieldtemplate "comment"
precomment = maybe "" render $ mfieldtemplate "precomment"
currency = maybe (fromMaybe "" mdefaultcurrency) render $ mfieldtemplate "currency"
amountstr = (currency++) $ negateIfParenthesised $ getAmountStr rules record
amountstr = (currency++) $ simplifySign $ negateIfParenthesised $ getAmountStr rules record
amount = either amounterror (Mixed . (:[])) $ runParser (evalStateT (amountp <* eof) mempty) "" $ T.pack amountstr
amounterror err = error' $ unlines
["error: could not parse \""++amountstr++"\" as an amount"
@ -711,6 +712,18 @@ getAmountStr rules record =
(Nothing, Just _, Just _) -> error' $ "both amount-in and amount-out have a value\n"++showRecord record
_ -> error' $ "found values for amount and for amount-in/amount-out - please use either amount or amount-in/amount-out\n"++showRecord record
-- From a String representing an Amount, simplify the sign by
-- removing '-' by pair from the left. It happens that some amount
-- strings contain 2 '-' because of CSV reading rules
simplifySign :: String -> String
simplifySign amount
| length indices < 2 = amount
| otherwise = simplifySign $ simplify2 amount
where
indices = findIndices (== '-') amount
simplify = delete '-'
simplify2 = simplify . simplify
negateIfParenthesised :: String -> String
negateIfParenthesised ('(':s) | lastMay s == Just ')' = negateStr $ init s
negateIfParenthesised s = s

View File

@ -93,3 +93,16 @@
>>>2 /using conversion rules file.*t.rules/
>>>=0
# 9. read CSV with rule double-negating column
rm -rf t.rules$$; printf 'skip 1\n\ncurrency $\n\nfields date, payee, payment\n\namount -%%payment\naccount1 liabilities:bank\naccount2 expense:other' >t.rules$$; echo 'date,payee,amount\n2009/10/9,Flubber Co,50\n2009/11/09,Merchant Credit,-60' | hledger -f- print --rules-file t.rules$$; rm -rf t.rules$$
>>>
2009/10/09
expense:other $50
liabilities:bank $-50
2009/11/09
expense:other $-60
liabilities:bank $60
>>>2 /using conversion rules file.*t.rules/
>>>=0