From 87a7a586d4387e9063edc1cc6b54dbaa5242b0f4 Mon Sep 17 00:00:00 2001 From: Stephen Morgan Date: Wed, 17 Nov 2021 10:12:55 +1100 Subject: [PATCH] fix: csv: Handle multiple zero amounts in postings in csv files. (#1733) --- hledger-lib/Hledger/Read/CsvReader.hs | 40 +++++++++++++-------------- hledger/test/csv.test | 18 ++++++++++++ 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/hledger-lib/Hledger/Read/CsvReader.hs b/hledger-lib/Hledger/Read/CsvReader.hs index 325e0f7ad..21d368b94 100644 --- a/hledger-lib/Hledger/Read/CsvReader.hs +++ b/hledger-lib/Hledger/Read/CsvReader.hs @@ -996,33 +996,31 @@ getAmount rules record currency p1IsVirtual n = ] -- if any of the numbered field names are present, discard all the unnumbered ones - assignments' | any isnumbered assignments = filter isnumbered assignments - | otherwise = assignments + discardUnnumbered xs = if null numbered then xs else numbered where - isnumbered (f,_) = T.any isDigit f + numbered = filter (T.any isDigit . fst) xs - -- if there's more than one value and only some are zeros, discard the zeros - assignments'' - | length assignments' > 1 && not (null nonzeros) = nonzeros - | otherwise = assignments' - where nonzeros = filter (not . mixedAmountLooksZero . snd) assignments' + -- discard all zero amounts, unless all amounts are zero, in which case discard all but the first + discardExcessZeros xs = if null nonzeros then take 1 xs else nonzeros + where + nonzeros = filter (not . mixedAmountLooksZero . snd) xs - in case -- dbg0 ("amounts for posting "++show n) - assignments'' of - [] -> Nothing - [(f,a)] | "-out" `T.isSuffixOf` f -> Just (maNegate a) -- for -out fields, flip the sign - -- XXX unless it's already negative ? back compat issues / too confusing ? - [(_,a)] -> Just a - fs -> error' . T.unpack . T.unlines $ [ -- PARTIAL: - "multiple non-zero amounts or multiple zero amounts assigned," + -- for -out fields, flip the sign XXX unless it's already negative ? back compat issues / too confusing ? + negateIfOut f = if "-out" `T.isSuffixOf` f then maNegate else id + + in case discardExcessZeros $ discardUnnumbered assignments of + [] -> Nothing + [(f,a)] -> Just $ negateIfOut f a + fs -> error' . T.unpack . T.unlines $ -- PARTIAL: + ["multiple non-zero amounts assigned," ,"please ensure just one. (https://hledger.org/csv.html#amount)" ," " <> showRecord record ," for posting: " <> T.pack (show n) - ] - ++ [" assignment: " <> f <> " " <> - fromMaybe "" (hledgerField rules record f) <> - "\t=> value: " <> wbToText (showMixedAmountB noColour a) -- XXX not sure this is showing all the right info - | (f,a) <- fs] + ] ++ + [" assignment: " <> f <> " " <> + fromMaybe "" (hledgerField rules record f) <> + "\t=> value: " <> wbToText (showMixedAmountB noColour a) -- XXX not sure this is showing all the right info + | (f,a) <- fs] -- | Figure out the expected balance (assertion or assignment) specified for posting N, -- if any (and its parse position). diff --git a/hledger/test/csv.test b/hledger/test/csv.test index 639b9a6bb..f678aa96b 100644 --- a/hledger/test/csv.test +++ b/hledger/test/csv.test @@ -996,6 +996,24 @@ $ ./csvtest.sh >=0 +# 49. Handle an entry with all zeros +< +Date;Description;Category;Debit;Credit;Balance +"2020-01-21","Client card point of sale fee",Fees,"0","0","1068.94" + +RULES +skip 1 +fields date, description, category, amount-out, amount-in, balance +currency $ +account1 assets:bank:checking + +$ ./csvtest.sh +2020-01-21 Client card point of sale fee + assets:bank:checking 0 = $1068.94 + expenses:unknown 0 + +>=0 + ## . #< #$ ./csvtest.sh