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 | ||||
|   filterJournalTransactions, | ||||
|   filterJournalPostings, | ||||
|   filterJournalRelatedPostings, | ||||
|   filterJournalAmounts, | ||||
|   filterTransactionAmounts, | ||||
|   filterTransactionPostings, | ||||
|   filterTransactionRelatedPostings, | ||||
|   filterPostingAmount, | ||||
|   -- * Mapping | ||||
|   journalMapTransactions, | ||||
| @ -105,7 +107,7 @@ import Data.Foldable (toList) | ||||
| import Data.Function ((&)) | ||||
| import qualified Data.HashTable.Class as H (toList) | ||||
| 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 qualified Data.Map.Strict as M | ||||
| 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 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. | ||||
| -- This can leave unbalanced transactions. | ||||
| filterJournalAmounts :: Query -> Journal -> Journal | ||||
| @ -534,6 +541,11 @@ filterPostingAmount q p@Posting{pamount=as} = p{pamount=filterMixedAmount (q `ma | ||||
| filterTransactionPostings :: Query -> Transaction -> Transaction | ||||
| 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. | ||||
| journalMapTransactions :: (Transaction -> Transaction) -> Journal -> Journal | ||||
| journalMapTransactions f j@Journal{jtxns=ts} = j{jtxns=map f ts} | ||||
|  | ||||
| @ -119,21 +119,22 @@ matchedPostingsBeforeAndDuring rspec@ReportSpec{_rsReportOpts=ropts,_rsQuery=q} | ||||
|   where | ||||
|     beforestartq = dbg3 "beforestartq" $ dateqtype $ DateSpan Nothing $ spanStart reportspan | ||||
|     beforeandduringps = | ||||
|       dbg5 "ps5" $ 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 related_ ropts then concatMap relatedPostings else id) $  -- with -r, replace each with its sibling postings | ||||
|       dbg5 "ps4" $ sortOn sortdate $                                          -- sort postings by date or date2 | ||||
|       dbg5 "ps3" $ (if invert_ ropts then map negatePostingAmount else id) $  -- with --invert, invert amounts | ||||
|                    journalPostings $ | ||||
|                    journalApplyValuationFromOpts rspec $                          -- convert to cost and apply valuation | ||||
|       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 | ||||
|                    journalApplyValuationFromOpts rspec $                      -- convert to cost and apply valuation | ||||
|       dbg5 "ps2" $ filterJournalAmounts symq $                                -- remove amount parts which the query's cur: terms would exclude | ||||
|       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 | ||||
|         beforeandduringq = dbg4 "beforeandduringq" $ And [depthless $ dateless q, beforeendq] | ||||
|           where | ||||
|             depthless  = filterQuery (not . queryIsDepth) | ||||
|             dateless   = filterQuery (not . queryIsDateOrDate2) | ||||
|             beforeendq = dateqtype $ DateSpan Nothing $ spanEnd reportspan | ||||
|         sortdate = if date2_ ropts then postingDate2 else postingDate | ||||
|         symq = dbg4 "symq" $ filterQuery queryIsSym q | ||||
|         depthless  = filterQuery (not . queryIsDepth) | ||||
|         dateless   = filterQuery (not . queryIsDateOrDate2) | ||||
|         beforeendq = dateqtype $ DateSpan Nothing $ spanEnd reportspan | ||||
| 
 | ||||
|     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 | ||||
|     dateqtype | ||||
|       | queryIsDate2 dateq || (queryIsDate dateq && date2_ ropts) = Date2 | ||||
|       | 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