From d2a9b5716fd2343ff05f25d05d3cffee0cb70335 Mon Sep 17 00:00:00 2001 From: Diogo Silva Date: Thu, 18 Jul 2024 23:16:03 +0200 Subject: [PATCH] Fixed transaction import comparison references across account only --- app.py | 19 +++++++++-- src/firefly_api/api_routes/account_api.py | 13 +++++--- src/firefly_sync_cli.py | 7 ++-- src/services/categorization_service.py | 38 ++++++++++++++-------- src/services/transaction_import_service.py | 3 +- 5 files changed, 56 insertions(+), 24 deletions(-) diff --git a/app.py b/app.py index 1d3c5bf..ff7f89a 100644 --- a/app.py +++ b/app.py @@ -74,7 +74,7 @@ def get_help_format(prog): help="Specific the start-date to link accounts (format: YYYY-MM-DD)", type=lambda s: datetime.strptime(s, '%Y-%m-%d')) parser_tx_link.add_argument('--end-date', - help="Specific the start-date to link accounts (format: YYYY-MM-DD)", + help="Specific the end-date to link accounts (format: YYYY-MM-DD)", type=lambda s: datetime.strptime(s, '%Y-%m-%d')) parser_tx_link.add_argument('--amount-diff', type=float, @@ -85,6 +85,16 @@ def get_help_format(prog): # Categorize transactions parser_tx_category = jobs.add_parser('tx-category', help="Categorize existing transactions (interactive)") + parser_tx_category.add_argument('--start-date', + help="Specific the start-date to categorize accounts (format: YYYY-MM-DD)", + type=lambda s: datetime.strptime(s, '%Y-%m-%d')) + parser_tx_category.add_argument('--end-date', + help="Specific the end-date to categorize accounts (format: YYYY-MM-DD)", + type=lambda s: datetime.strptime(s, '%Y-%m-%d')) + parser_tx_category.add_argument('--account-ids', + type=str, + help="Account IDs separated by comma (e.g: 3,4,7)", + default="") args = parser.parse_args() @@ -99,4 +109,9 @@ def get_help_format(prog): amount_diff_percentage=args.amount_diff, date_diff_days=args.date_diff) elif args.job == 'tx-category': - firefly_sync_cli.categorize() + firefly_sync_cli.categorize( + start_date=args.start_date, end_date=args.end_date, + account_ids=[account_id + for account_ids in args.account_ids + for account_id in account_ids.split(',') + if account_id]) diff --git a/src/firefly_api/api_routes/account_api.py b/src/firefly_api/api_routes/account_api.py index 3e643e1..a21f63d 100644 --- a/src/firefly_api/api_routes/account_api.py +++ b/src/firefly_api/api_routes/account_api.py @@ -17,9 +17,14 @@ def get_accounts(self, type: AccountType): data = self._internal_get('/', params={'type': type.value}) return [Account(id=item["id"], **item['attributes']) for item in data] - def get_account_transactions(self, account_id: str, start_date: datetime, end_date: datetime) -> List[Transaction]: - data = self._internal_get( - f'{account_id}/transactions', params={'start': start_date.strftime(BaseApi.DATE_FORMAT), - 'end': end_date.strftime(BaseApi.DATE_FORMAT)}) + def get_account_transactions(self, account_id: str, start_date: datetime = None, + end_date: datetime = None) -> List[Transaction]: + params = {} + if start_date is not None: + params['start'] = start_date.strftime(BaseApi.DATE_FORMAT) + if end_date is not None: + params['end'] = end_date.strftime(BaseApi.DATE_FORMAT) + + data = self._internal_get(f'{account_id}/transactions', params=params) return [Transaction(id=item['id'], **item['attributes']['transactions'][0]) for item in data] diff --git a/src/firefly_sync_cli.py b/src/firefly_sync_cli.py index 9d381f0..8f2a20d 100644 --- a/src/firefly_sync_cli.py +++ b/src/firefly_sync_cli.py @@ -1,5 +1,5 @@ import logging -from typing import Any +from typing import Any, List from datetime import datetime from .firefly_api.api import FireflyApi @@ -25,8 +25,9 @@ def create_cron_job(self, cli_token) -> Any: data = self.api.cron.create_cron_job(cli_token) logging.info(f'Cron job run sucessfully: {data}') - def categorize(self): - CategorizationService(self.api, self.dry_run).interactive_categorize() + def categorize(self, start_date: datetime = None, end_date: datetime = None, account_ids: List[str] = None): + CategorizationService(self.api, self.dry_run).interactive_categorize( + start_date=start_date, end_date=end_date, account_ids=account_ids) def import_file(self, file: str) -> bool: return TransactionImportService(self.api, self.dry_run).import_file(file=file) diff --git a/src/services/categorization_service.py b/src/services/categorization_service.py index dadea10..a59997d 100644 --- a/src/services/categorization_service.py +++ b/src/services/categorization_service.py @@ -1,8 +1,10 @@ -from datetime import datetime, timedelta +from datetime import datetime +from typing import List from .base_service import BaseService -from ..firefly_api.models.transaction_type import TransactionType +from ..firefly_api.models.account_type import AccountType from ..firefly_api.api import FireflyApi +import logging class CategorizationService(BaseService): @@ -10,17 +12,27 @@ class CategorizationService(BaseService): def __init__(self, api: FireflyApi, dry_run: bool) -> None: super().__init__(api, dry_run) - def interactive_categorize(self): - transactions = self.api.transactions.get_transactions(transaction_type=TransactionType.ALL, - start_date=datetime.now() - timedelta(days=30)) + def interactive_categorize(self, start_date: datetime = None, end_date: datetime = None, + account_ids: List[str] = []): + accounts = self.api.accounts.get_accounts(type=AccountType.ASSET) categories = self.api.categories.get_categories() - for transaction in transactions: - for index, category in enumerate(categories): - print(f"{index + 1}. {category.name}", end=', ' if index != len(categories) - 1 else None) - print(f"Transaction: {transaction.description} | {transaction.amount} {transaction.currency_code} " - f"| {transaction.type} | {transaction.date}") + for account in accounts: + if len(account_ids) != 0 and account.id not in account_ids: + continue - selected_category_index = BaseService._get_allowed_input(len(categories) - 1) - selected_category = categories[selected_category_index] - print(selected_category) + logging.info(f'Getting transactions for account \'{account.name}\'') + transactions = self.api.accounts.get_account_transactions( + account_id=account.id, + start_date=start_date, + end_date=end_date) + + for transaction in transactions: + for index, category in enumerate(categories): + print(f"{index + 1}. {category.name}", end=', ' if index != len(categories) - 1 else None) + print(f"Transaction: {transaction.description} | {transaction.amount} {transaction.currency_code} " + f"| {transaction.type} | {transaction.date}") + + selected_category_index = BaseService._get_allowed_input(len(categories) - 1) + selected_category = categories[selected_category_index] + print(selected_category) diff --git a/src/services/transaction_import_service.py b/src/services/transaction_import_service.py index f6f59c2..711d372 100644 --- a/src/services/transaction_import_service.py +++ b/src/services/transaction_import_service.py @@ -44,8 +44,7 @@ def import_file(self, file: str) -> bool: start_date = min(t.date for t in parsed_transactions) end_date = max(t.date for t in parsed_transactions) - stored_transactions = self.api.accounts.get_account_transactions( - account_id=account.id, start_date=start_date, end_date=end_date) + stored_transactions = self.api.transactions.get_transactions(start_date=start_date, end_date=end_date) stored_transactions_by_reference = { hash_part.strip(): t