reconciler: Add --full-months option to round statement dates to month boundaries
This commit is contained in:
		
							parent
							
								
									07d7737bd0
								
							
						
					
					
						commit
						8b08997fda
					
				
					 2 changed files with 38 additions and 0 deletions
				
			
		|  | @ -295,6 +295,20 @@ def format_multirecord(r1s: List[dict], r2s: List[dict], note: str) -> List[list | |||
|     return match_output | ||||
| 
 | ||||
| 
 | ||||
| def _start_of_month(time, offset_months=0): | ||||
|     if offset_months > 0: | ||||
|         return _start_of_month(time.replace(day=28) + datetime.timedelta(days=4), offset_months - 1) | ||||
|     else: | ||||
|         return time.replace(day=1) | ||||
| 
 | ||||
| 
 | ||||
| def round_to_month(begin_date, end_date): | ||||
|     """Round a beginning and end date to beginning and end of months respectively.""" | ||||
|     return ( | ||||
|         _start_of_month(begin_date), | ||||
|         _start_of_month(end_date, offset_months=1) - datetime.timedelta(days=1)) | ||||
| 
 | ||||
| 
 | ||||
| def sort_records(records: List) -> List: | ||||
|     return sorted(records, key=lambda x: (x['date'], x['amount'])) | ||||
| 
 | ||||
|  | @ -596,6 +610,7 @@ def parse_arguments(argv: List[str]) -> argparse.Namespace: | |||
|     # parser.add_argument('--report-group-regex') | ||||
|     parser.add_argument('--show-reconciled-matches', action='store_true') | ||||
|     parser.add_argument('--non-interactive', action='store_true', help="Don't prompt to write to the books")    # parser.add_argument('--statement-balance', type=parse_decimal_with_separator, required=True, help="A.K.A \"cleared balance\" taken from the end of the period on the PDF statement. Required because CSV statements don't include final or running totals") | ||||
|     parser.add_argument('--full-months', action='store_true', help='Match payments over the full month, rather that just between the beginning and end dates of the CSV statement') | ||||
|     args = parser.parse_args(args=argv) | ||||
|     return args | ||||
| 
 | ||||
|  | @ -676,6 +691,9 @@ def main(arglist: Optional[Sequence[str]] = None, | |||
|     begin_date = statement_trans[0]['date'] | ||||
|     end_date = statement_trans[-1]['date'] | ||||
| 
 | ||||
|     if args.full_months: | ||||
|         begin_date, end_date = round_to_month(begin_date, end_date) | ||||
| 
 | ||||
|     # Query for the Beancount books data for this above period. | ||||
|     # | ||||
|     # There are pros and cons for using Beancount's in-memory entries | ||||
|  |  | |||
|  | @ -5,6 +5,8 @@ import os | |||
| import tempfile | ||||
| import textwrap | ||||
| 
 | ||||
| import pytest | ||||
| 
 | ||||
| from conservancy_beancount.reconcile.statement_reconciler import ( | ||||
|     date_proximity, | ||||
|     format_output, | ||||
|  | @ -15,6 +17,7 @@ from conservancy_beancount.reconcile.statement_reconciler import ( | |||
|     read_fr_csv, | ||||
|     remove_duplicate_words, | ||||
|     remove_payee_junk, | ||||
|     round_to_month, | ||||
|     subset_match, | ||||
|     totals, | ||||
|     write_metadata_to_books, | ||||
|  | @ -388,3 +391,20 @@ def test_format_output(): | |||
|     matches, _, _ = match_statement_and_books(statement, books) | ||||
|     output = format_output(matches, datetime.date(2022, 1, 1), datetime.date(2022, 2, 1), 'test.csv', True) | ||||
|     assert '2022-01-01:       10.00 Patreon         / Patreon   / 12345  →  2022-01-01:       10.00 Patreon                              ✓ Matched' in output | ||||
| 
 | ||||
| 
 | ||||
| month_test_data = [ | ||||
|     ((datetime.date(2022, 1, 2), datetime.date(2022, 1, 30)), | ||||
|      (datetime.date(2022, 1, 1), datetime.date(2022, 1, 31))), | ||||
|     ((datetime.date(2022, 4, 2), datetime.date(2022, 4, 29)), | ||||
|      (datetime.date(2022, 4, 1), datetime.date(2022, 4, 30))), | ||||
|     ((datetime.date(2022, 2, 2), datetime.date(2022, 2, 27)), | ||||
|      (datetime.date(2022, 2, 1), datetime.date(2022, 2, 28))), | ||||
|     ((datetime.date(2024, 2, 2), datetime.date(2024, 2, 27)), | ||||
|      (datetime.date(2024, 2, 1), datetime.date(2024, 2, 29))), | ||||
| ] | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.parametrize('input_dates,rounded_dates', month_test_data) | ||||
| def test_rounds_to_full_month(input_dates, rounded_dates): | ||||
|     assert round_to_month(*input_dates) == rounded_dates | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue