fix: reg: register --related should not create duplicate postings when
more than one posting in a transaction matches. (#1629)
This commit is contained in:
		
							parent
							
								
									6528f25593
								
							
						
					
					
						commit
						9df574b3c0
					
				| @ -31,9 +31,11 @@ module Hledger.Data.Journal ( | |||||||
|   -- * Filtering |   -- * Filtering | ||||||
|   filterJournalTransactions, |   filterJournalTransactions, | ||||||
|   filterJournalPostings, |   filterJournalPostings, | ||||||
|  |   filterJournalRelatedPostings, | ||||||
|   filterJournalAmounts, |   filterJournalAmounts, | ||||||
|   filterTransactionAmounts, |   filterTransactionAmounts, | ||||||
|   filterTransactionPostings, |   filterTransactionPostings, | ||||||
|  |   filterTransactionRelatedPostings, | ||||||
|   filterPostingAmount, |   filterPostingAmount, | ||||||
|   -- * Mapping |   -- * Mapping | ||||||
|   journalMapTransactions, |   journalMapTransactions, | ||||||
| @ -105,7 +107,7 @@ import Data.Foldable (toList) | |||||||
| import Data.Function ((&)) | import Data.Function ((&)) | ||||||
| import qualified Data.HashTable.Class as H (toList) | import qualified Data.HashTable.Class as H (toList) | ||||||
| import qualified Data.HashTable.ST.Cuckoo as H | import qualified Data.HashTable.ST.Cuckoo as H | ||||||
| import Data.List (find, foldl', sortOn) | import Data.List ((\\), find, foldl', sortOn) | ||||||
| import Data.List.Extra (nubSort) | import Data.List.Extra (nubSort) | ||||||
| import qualified Data.Map.Strict as M | import qualified Data.Map.Strict as M | ||||||
| import Data.Maybe (catMaybes, fromJust, fromMaybe, isJust, mapMaybe, maybeToList) | import Data.Maybe (catMaybes, fromJust, fromMaybe, isJust, mapMaybe, maybeToList) | ||||||
| @ -517,6 +519,11 @@ filterJournalTransactions q j@Journal{jtxns=ts} = j{jtxns=filter (q `matchesTran | |||||||
| filterJournalPostings :: Query -> Journal -> Journal | filterJournalPostings :: Query -> Journal -> Journal | ||||||
| filterJournalPostings q j@Journal{jtxns=ts} = j{jtxns=map (filterTransactionPostings q) ts} | filterJournalPostings q j@Journal{jtxns=ts} = j{jtxns=map (filterTransactionPostings q) ts} | ||||||
| 
 | 
 | ||||||
|  | -- | Keep only postings which do not match the query expression, but for which a related posting does. | ||||||
|  | -- This can leave unbalanced transactions. | ||||||
|  | filterJournalRelatedPostings :: Query -> Journal -> Journal | ||||||
|  | filterJournalRelatedPostings q j@Journal{jtxns=ts} = j{jtxns=map (filterTransactionRelatedPostings q) ts} | ||||||
|  | 
 | ||||||
| -- | Within each posting's amount, keep only the parts matching the query. | -- | Within each posting's amount, keep only the parts matching the query. | ||||||
| -- This can leave unbalanced transactions. | -- This can leave unbalanced transactions. | ||||||
| filterJournalAmounts :: Query -> Journal -> Journal | filterJournalAmounts :: Query -> Journal -> Journal | ||||||
| @ -534,6 +541,11 @@ filterPostingAmount q p@Posting{pamount=as} = p{pamount=filterMixedAmount (q `ma | |||||||
| filterTransactionPostings :: Query -> Transaction -> Transaction | filterTransactionPostings :: Query -> Transaction -> Transaction | ||||||
| filterTransactionPostings q t@Transaction{tpostings=ps} = t{tpostings=filter (q `matchesPosting`) ps} | filterTransactionPostings q t@Transaction{tpostings=ps} = t{tpostings=filter (q `matchesPosting`) ps} | ||||||
| 
 | 
 | ||||||
|  | filterTransactionRelatedPostings :: Query -> Transaction -> Transaction | ||||||
|  | filterTransactionRelatedPostings q t@Transaction{tpostings=ps} = | ||||||
|  |     t{tpostings=if null matches then [] else ps \\ matches} | ||||||
|  |   where matches = filter (matchesPosting q) ps | ||||||
|  | 
 | ||||||
| -- | Apply a transformation to a journal's transactions. | -- | Apply a transformation to a journal's transactions. | ||||||
| journalMapTransactions :: (Transaction -> Transaction) -> Journal -> Journal | journalMapTransactions :: (Transaction -> Transaction) -> Journal -> Journal | ||||||
| journalMapTransactions f j@Journal{jtxns=ts} = j{jtxns=map f ts} | journalMapTransactions f j@Journal{jtxns=ts} = j{jtxns=map f ts} | ||||||
|  | |||||||
| @ -119,21 +119,22 @@ matchedPostingsBeforeAndDuring rspec@ReportSpec{_rsReportOpts=ropts,_rsQuery=q} | |||||||
|   where |   where | ||||||
|     beforestartq = dbg3 "beforestartq" $ dateqtype $ DateSpan Nothing $ spanStart reportspan |     beforestartq = dbg3 "beforestartq" $ dateqtype $ DateSpan Nothing $ spanStart reportspan | ||||||
|     beforeandduringps = |     beforeandduringps = | ||||||
|       dbg5 "ps5" $ sortOn sortdate $                                             -- sort postings by date or date2 |       dbg5 "ps4" $ sortOn sortdate $                                          -- sort postings by date or date2 | ||||||
|       dbg5 "ps4" $ (if invert_ ropts then map negatePostingAmount else id) $     -- with --invert, invert amounts |       dbg5 "ps3" $ (if invert_ ropts then map negatePostingAmount else id) $  -- with --invert, invert amounts | ||||||
|       dbg5 "ps3" $ (if related_ ropts then concatMap relatedPostings else id) $  -- with -r, replace each with its sibling postings |  | ||||||
|                    journalPostings $ |                    journalPostings $ | ||||||
|                    journalApplyValuationFromOpts rspec $                          -- convert to cost and apply valuation |                    journalApplyValuationFromOpts rspec $                      -- convert to cost and apply valuation | ||||||
|       dbg5 "ps2" $ filterJournalAmounts symq $                                    -- remove amount parts which the query's cur: terms would exclude |       dbg5 "ps2" $ filterJournalAmounts symq $                                -- remove amount parts which the query's cur: terms would exclude | ||||||
|       dbg5 "ps1" $ filterJournalPostings beforeandduringq j                       -- filter postings by the query, with no start date or depth limit |       dbg5 "ps1" $ filterJournal beforeandduringq j                           -- filter postings by the query, with no start date or depth limit | ||||||
|  | 
 | ||||||
|  |     beforeandduringq = dbg4 "beforeandduringq" $ And [depthless $ dateless q, beforeendq] | ||||||
|       where |       where | ||||||
|         beforeandduringq = dbg4 "beforeandduringq" $ And [depthless $ dateless q, beforeendq] |         depthless  = filterQuery (not . queryIsDepth) | ||||||
|           where |         dateless   = filterQuery (not . queryIsDateOrDate2) | ||||||
|             depthless  = filterQuery (not . queryIsDepth) |         beforeendq = dateqtype $ DateSpan Nothing $ spanEnd reportspan | ||||||
|             dateless   = filterQuery (not . queryIsDateOrDate2) | 
 | ||||||
|             beforeendq = dateqtype $ DateSpan Nothing $ spanEnd reportspan |     sortdate = if date2_ ropts then postingDate2 else postingDate | ||||||
|         sortdate = if date2_ ropts then postingDate2 else postingDate |     filterJournal = if related_ ropts then filterJournalRelatedPostings else filterJournalPostings  -- with -r, replace each posting with its sibling postings | ||||||
|         symq = dbg4 "symq" $ filterQuery queryIsSym q |     symq = dbg4 "symq" $ filterQuery queryIsSym q | ||||||
|     dateqtype |     dateqtype | ||||||
|       | queryIsDate2 dateq || (queryIsDate dateq && date2_ ropts) = Date2 |       | queryIsDate2 dateq || (queryIsDate dateq && date2_ ropts) = Date2 | ||||||
|       | otherwise = Date |       | otherwise = Date | ||||||
|  | |||||||
							
								
								
									
										17
									
								
								hledger/test/register/related.test
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								hledger/test/register/related.test
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | # 1. related postings will only display each posting once | ||||||
|  | < | ||||||
|  | P 2021-01-01 A  10 B | ||||||
|  | 
 | ||||||
|  | 2021-01-01 | ||||||
|  |   (a)    1 A | ||||||
|  |   (a)    2 A | ||||||
|  |   (b)    3 A | ||||||
|  | 
 | ||||||
|  | $ hledger -f- register a --related | ||||||
|  | 2021-01-01                      (b)                            3 A           3 A | ||||||
|  | >= | ||||||
|  | 
 | ||||||
|  | # 2. related postings will display valued postings when requested | ||||||
|  | $ hledger -f- register a --related -V | ||||||
|  | 2021-01-01                      (b)                           30 B          30 B | ||||||
|  | >= | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user