;csv: amount-setting notes, doc improvements from reddit discussion
https://www.reddit.com/r/plaintextaccounting/comments/nxu1ss/hledger_parsing_csv_with_negative_amount_in_debit/
This commit is contained in:
parent
665fec83cd
commit
b81f8f768d
@ -974,9 +974,10 @@ transactionFromCsvRecord sourcepos rules record = t
|
|||||||
-- If there's multiple non-zeros, or no non-zeros but multiple zeros, it throws an error.
|
-- If there's multiple non-zeros, or no non-zeros but multiple zeros, it throws an error.
|
||||||
getAmount :: CsvRules -> CsvRecord -> Text -> Bool -> Int -> Maybe MixedAmount
|
getAmount :: CsvRules -> CsvRecord -> Text -> Bool -> Int -> Maybe MixedAmount
|
||||||
getAmount rules record currency p1IsVirtual n =
|
getAmount rules record currency p1IsVirtual n =
|
||||||
-- Warning, many tricky corner cases here.
|
-- Warning! Many tricky corner cases here.
|
||||||
-- docs: hledger_csv.m4.md #### amount
|
-- Keep synced with:
|
||||||
-- tests: hledger/test/csv.test ~ 13, 31-34
|
-- hledger_csv.m4.md -> CSV FORMAT -> "amount", "Setting amounts",
|
||||||
|
-- hledger/test/csv.test -> 13, 31-34
|
||||||
let
|
let
|
||||||
unnumberedfieldnames = ["amount","amount-in","amount-out"]
|
unnumberedfieldnames = ["amount","amount-in","amount-out"]
|
||||||
|
|
||||||
@ -990,6 +991,7 @@ getAmount rules record currency p1IsVirtual n =
|
|||||||
assignments = [(f,a') | f <- fieldnames
|
assignments = [(f,a') | f <- fieldnames
|
||||||
, Just v <- [T.strip . renderTemplate rules record <$> hledgerField rules record f]
|
, Just v <- [T.strip . renderTemplate rules record <$> hledgerField rules record f]
|
||||||
, not $ T.null v
|
, not $ T.null v
|
||||||
|
-- XXX maybe ignore rule-generated values like "", "-", "$", "-$", "$-" ? cf CSV FORMAT -> "amount", "Setting amounts",
|
||||||
, let a = parseAmount rules record currency v
|
, let a = parseAmount rules record currency v
|
||||||
-- With amount/amount-in/amount-out, in posting 2,
|
-- With amount/amount-in/amount-out, in posting 2,
|
||||||
-- flip the sign and convert to cost, as they did before 1.17
|
-- flip the sign and convert to cost, as they did before 1.17
|
||||||
@ -1012,6 +1014,7 @@ getAmount rules record currency p1IsVirtual n =
|
|||||||
assignments'' of
|
assignments'' of
|
||||||
[] -> Nothing
|
[] -> Nothing
|
||||||
[(f,a)] | "-out" `T.isSuffixOf` f -> Just (maNegate a) -- for -out fields, flip the sign
|
[(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
|
[(_,a)] -> Just a
|
||||||
fs -> error' . T.unpack . T.unlines $ [ -- PARTIAL:
|
fs -> error' . T.unpack . T.unlines $ [ -- PARTIAL:
|
||||||
"multiple non-zero amounts or multiple zero amounts assigned,"
|
"multiple non-zero amounts or multiple zero amounts assigned,"
|
||||||
|
|||||||
@ -3581,20 +3581,18 @@ a default account name will be chosen (like "expenses:unknown" or "income:unknow
|
|||||||
|
|
||||||
##### amount
|
##### amount
|
||||||
|
|
||||||
`amountN` sets posting N's amount.
|
`amountN` sets the Nth posting's amount.
|
||||||
If the CSV uses separate fields for inflows and outflows, you can
|
By assigning to `amount1`, `amount2`, ... etc. you can generate up to 99 postings.
|
||||||
use `amountN-in` and `amountN-out` instead.
|
|
||||||
By assigning to `amount1`, `amount2`, ... etc. you can generate anywhere
|
|
||||||
from 0 to 99 postings.
|
|
||||||
|
|
||||||
There is also an older, unnumbered form of these names, suitable for
|
If the CSV uses separate fields for debits and credits (inflows and outflows), you can
|
||||||
2-posting transactions, which sets both posting 1's and (negated) posting 2's amount:
|
use `amountN-in` and `amountN-out` instead.
|
||||||
`amount`, or `amount-in` and `amount-out`.
|
Note hledger assumes both of these fields are unsigned, and will automatically negate the "-out" value.
|
||||||
This is still supported
|
If the fields are signed, see ["Setting amounts"](#setting-amounts) below.
|
||||||
because it keeps pre-hledger-1.17 csv rules files working,
|
|
||||||
and because it can be more succinct,
|
There is also an unnumbered form of these names: `amount`, or `amount-in` and `amount-out`.
|
||||||
and because it converts posting 2's amount to cost if there's a
|
This is supported to keep pre-hledger-1.17 CSV rules files working (and for occasional convenience).
|
||||||
[transaction price](#transaction-prices), which can be useful.
|
It is suitable only for two-posting transactions; it sets both posting 1's and posting 2's amount.
|
||||||
|
Posting 2's amount will be negated, and also converted to cost if there's a [transaction price](#transaction-prices).
|
||||||
|
|
||||||
If you have an existing rules file using the unnumbered form, you
|
If you have an existing rules file using the unnumbered form, you
|
||||||
might want to use the numbered form in certain conditional blocks,
|
might want to use the numbered form in certain conditional blocks,
|
||||||
@ -4041,22 +4039,27 @@ Here are the ways to set a posting's amount:
|
|||||||
Assign (via a [fields list](#fields) or a [field assignment](#field-assignment)) to `amountN`.
|
Assign (via a [fields list](#fields) or a [field assignment](#field-assignment)) to `amountN`.
|
||||||
This sets the Nth posting's amount. N is usually 1 or 2 but can go up to 99.
|
This sets the Nth posting's amount. N is usually 1 or 2 but can go up to 99.
|
||||||
|
|
||||||
2. **If the CSV has separate Debit and Credit amount fields:**\
|
2. **If the CSV has separate amount fields for debit & credit (in & out):**\
|
||||||
|
|
||||||
|
a. **If both fields are unsigned:**\
|
||||||
Assign to `amountN-in` and `amountN-out`.
|
Assign to `amountN-in` and `amountN-out`.
|
||||||
This sets posting N's amount to whichever of these has a non-zero value,
|
This sets posting N's amount to whichever of these has a non-zero value,
|
||||||
guessing an appropriate sign.
|
and negates the "-out" value.
|
||||||
|
|
||||||
- **If hledger guesses the wrong sign:**\
|
b. **If either field is signed (can contain a minus sign):**\
|
||||||
Prepend a minus sign to flip it. Eg:
|
Use a [conditional rule](#if-block) to flip the sign (of non-empty values).
|
||||||
|
Since hledger always negates amountN-out, if it was already negative,
|
||||||
|
we must undo that by negating once more (but only if the field is non-empty):
|
||||||
|
|
||||||
```rules
|
```rules
|
||||||
fields date, description, amount-in, amount-out
|
fields date, description, amount1-in, amount1-out
|
||||||
amount-out -%amount-out
|
if %amount1-out [1-9]
|
||||||
|
amount1-out -%amount1-out
|
||||||
```
|
```
|
||||||
|
|
||||||
- **If both fields contain a non-zero value:**\
|
c. **If both fields, or neither field, can contain a non-zero value:**\
|
||||||
The `amountN-in`/`amountN-out` rules require that each CSV record has a non-zero value in exactly one of the two fields,
|
hledger normally expects exactly one of the fields to have a non-zero value.
|
||||||
so that hledger knows which to choose. So these would all be rejected:
|
Eg, the `amountN-in`/`amountN-out` rules would reject values like these:
|
||||||
|
|
||||||
```csv
|
```csv
|
||||||
"" , ""
|
"" , ""
|
||||||
@ -4064,8 +4067,9 @@ Here are the ways to set a posting's amount:
|
|||||||
"1" , "none"
|
"1" , "none"
|
||||||
```
|
```
|
||||||
|
|
||||||
If your CSV has amount values like this, use [conditional rules](#if-block) instead.
|
So, use [conditional rules](#if-block) to set the amount from the appropriate field.
|
||||||
For example, to make hledger to choose the value containing non-zero digits:
|
Eg, these rules would make it use only the value containing non-zero digits,
|
||||||
|
handling the above:
|
||||||
|
|
||||||
```rules
|
```rules
|
||||||
fields date, description, in, out
|
fields date, description, in, out
|
||||||
@ -4075,10 +4079,9 @@ Here are the ways to set a posting's amount:
|
|||||||
amount1 %out
|
amount1 %out
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Using the old numberless syntax:**\
|
3. **If you are stuck with hledger <1.17, or you want posting 2's amount converted to cost:**\
|
||||||
Assign to `amount` (or to `amount-in` and `amount-out`).
|
Use the old numberless syntax, which sets amount1 and amount2:
|
||||||
This sets posting 1's and posting 2's amounts (and converts posting 2's amount to cost).
|
assign to `amount` (or to `amount-in` and `amount-out`).
|
||||||
This is supported for backwards compatibility (and occasional convenience).
|
|
||||||
|
|
||||||
4. **If the CSV has the balance instead of the transaction amount:**\
|
4. **If the CSV has the balance instead of the transaction amount:**\
|
||||||
Assign to `balanceN`, which sets posting N's amount indirectly via a
|
Assign to `balanceN`, which sets posting N's amount indirectly via a
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user