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:
		
							parent
							
								
									a4293dca6e
								
							
						
					
					
						commit
						309d1ccd59
					
				@ -35,6 +35,7 @@ import Control.Monad.Except
 | 
				
			|||||||
import Control.Monad.State.Strict (StateT, get, modify', evalStateT)
 | 
					import Control.Monad.State.Strict (StateT, get, modify', evalStateT)
 | 
				
			||||||
-- import Test.HUnit
 | 
					-- import Test.HUnit
 | 
				
			||||||
import Data.Char (toLower, isDigit, isSpace)
 | 
					import Data.Char (toLower, isDigit, isSpace)
 | 
				
			||||||
 | 
					import Data.List (findIndices)
 | 
				
			||||||
import Data.List.Compat
 | 
					import Data.List.Compat
 | 
				
			||||||
import Data.Maybe
 | 
					import Data.Maybe
 | 
				
			||||||
import Data.Ord
 | 
					import Data.Ord
 | 
				
			||||||
@ -641,7 +642,7 @@ transactionFromCsvRecord sourcepos rules record = t
 | 
				
			|||||||
    comment     = maybe "" render $ mfieldtemplate "comment"
 | 
					    comment     = maybe "" render $ mfieldtemplate "comment"
 | 
				
			||||||
    precomment  = maybe "" render $ mfieldtemplate "precomment"
 | 
					    precomment  = maybe "" render $ mfieldtemplate "precomment"
 | 
				
			||||||
    currency    = maybe (fromMaybe "" mdefaultcurrency) render $ mfieldtemplate "currency"
 | 
					    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
 | 
					    amount      = either amounterror (Mixed . (:[])) $ runParser (evalStateT (amountp <* eof) mempty) "" $ T.pack amountstr
 | 
				
			||||||
    amounterror err = error' $ unlines
 | 
					    amounterror err = error' $ unlines
 | 
				
			||||||
      ["error: could not parse \""++amountstr++"\" as an amount"
 | 
					      ["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
 | 
					    (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
 | 
					    _                           -> 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 :: String -> String
 | 
				
			||||||
negateIfParenthesised ('(':s) | lastMay s == Just ')' = negateStr $ init s
 | 
					negateIfParenthesised ('(':s) | lastMay s == Just ')' = negateStr $ init s
 | 
				
			||||||
negateIfParenthesised s                               = s
 | 
					negateIfParenthesised s                               = s
 | 
				
			||||||
 | 
				
			|||||||
@ -93,3 +93,16 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
>>>2 /using conversion rules file.*t.rules/
 | 
					>>>2 /using conversion rules file.*t.rules/
 | 
				
			||||||
>>>=0
 | 
					>>>=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
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user