;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,31 +4039,37 @@ 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 | ||||||
|       "",  "" |       ""          ,  "" | ||||||
|       "0", "0" |       "0"         , "0" | ||||||
|       "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