From 3cc79a67f27fab4a4a8283b89f0681c0471a9d76 Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Sun, 5 Apr 2020 14:17:06 -0700 Subject: [PATCH] csv: don't discard explicit assignments of a 0 amount Eg: an `amount1 $0.00` assignment was generating a posting1 with missing amount. --- hledger-lib/Hledger/Read/CsvReader.hs | 30 ++++++++++++++++++--------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/hledger-lib/Hledger/Read/CsvReader.hs b/hledger-lib/Hledger/Read/CsvReader.hs index 2a2abe8c0..56550c01c 100644 --- a/hledger-lib/Hledger/Read/CsvReader.hs +++ b/hledger-lib/Hledger/Read/CsvReader.hs @@ -859,37 +859,47 @@ transactionFromCsvRecord sourcepos rules record = t } -- | Figure out the amount specified for posting N, if any. --- Looks for a non-zero amount assigned to one of "amountN", "amountN-in", "amountN-out". --- Postings 1 or 2 also look at "amount", "amount-in", "amount-out". --- Throws an error if more than one of these has a non-zero amount assigned. -- A currency symbol to prepend to the amount, if any, is provided, -- and whether posting 1 requires balancing or not. +-- This looks for a non-empty amount value assigned to "amountN", "amountN-in", or "amountN-out". +-- For postings 1 or 2 it also looks at "amount", "amount-in", "amount-out". +-- If more than one of these has a value, it looks for one that is non-zero. +-- If there's multiple non-zeros, or no non-zeros but multiple zeros, it throws an error. getAmount :: CsvRules -> CsvRecord -> String -> Bool -> Int -> Maybe MixedAmount getAmount rules record currency p1IsVirtual n = + -- The corner cases are tricky here. let unnumberedfieldnames = ["amount","amount-in","amount-out"] fieldnames = map (("amount"++show n)++) ["","-in","-out"] -- For posting 1, also recognise the old amount/amount-in/amount-out names. -- For posting 2, the same but only if posting 1 needs balancing. ++ if n==1 || n==2 && not p1IsVirtual then unnumberedfieldnames else [] - nonzeroamounts = [(f,a') | f <- fieldnames + nonemptyamounts = [(f,a') | f <- fieldnames , Just v@(_:_) <- [strip . renderTemplate rules record <$> hledgerField rules record f] , let a = parseAmount rules record currency v - , not $ isZeroMixedAmount a -- With amount/amount-in/amount-out, in posting 2, -- flip the sign and convert to cost, as they did before 1.17 , let a' = if f `elem` unnumberedfieldnames && n==2 then costOfMixedAmount (-a) else a ] + -- If there's more than one non-empty amount, ignore the zeros. + -- Unless they're all zeros. + amounts + | length nonemptyamounts <= 1 = nonemptyamounts + | otherwise = + if null nonzeros then zeros else nonzeros + where (zeros,nonzeros) = partition (isZeroMixedAmount . snd) nonemptyamounts + -- if there's "amount" and "amountN"s, just discard the former - nonzeroamounts' - | length nonzeroamounts > 1 = filter ((/="amount").fst) nonzeroamounts - | otherwise = nonzeroamounts - in case nonzeroamounts' of + amounts' + | length amounts > 1 = filter ((/="amount").fst) amounts + | otherwise = amounts + + in case amounts' of [] -> Nothing [(f,a)] | "-out" `isSuffixOf` f -> Just (-a) -- for -out fields, flip the sign [(_,a)] -> Just a fs -> error' $ - "more than one non-zero amount for this record, please ensure just one\n" + "more than one non-zero amount for this record, or multiple zeros - please ensure just one\n" ++ " " ++ showRecord record ++ "\n" ++ unlines [" rule: " ++ f ++ " " ++ fromMaybe "" (hledgerField rules record f) ++