diff --git a/ynab.py b/ynab.py index 45ca923..4c39f43 100755 --- a/ynab.py +++ b/ynab.py @@ -8,9 +8,13 @@ import os import sys import glob import re +import argparse +import logging import pandas as pd from pathlib import Path +logger = logging.getLogger(__name__) + def parse_norwegian_number(value): """Convert Norwegian number format (comma decimal) to float""" if pd.isna(value) or value == '': @@ -30,7 +34,7 @@ def parse_norwegian_date(date_str): # Parse DD.MM.YYYY and convert to date object return pd.to_datetime(date_str, format='%d.%m.%Y') except (ValueError, TypeError): - print(f"Invalid date format: {date_str}") + logger.error(f"Invalid date format: {date_str}") exit(1) def convert_memo(original): @@ -184,7 +188,7 @@ def process_bank_statement(file_path, parse_function, delimiter, encoding): elif file_extension in [".xlsx", ".xls"]: data = pd.read_excel(file_path) else: - print(f"Skipping unsupported file type: {file_path}") + logger.warning(f"Skipping unsupported file type: {file_path}") return pd.DataFrame() # Call the appropriate bank-specific parsing function @@ -192,7 +196,7 @@ def process_bank_statement(file_path, parse_function, delimiter, encoding): return ynab_data except Exception as e: - print(f"Error processing file {file_path}: {e}") + logger.error(f"Error processing file {file_path}: {e}") raise e return pd.DataFrame() @@ -217,26 +221,30 @@ def find_bank_config(filename): return None, None -def convert_bank_statements_to_ynab(input_files=None): +def convert_bank_statements_to_ynab(input_files, output_directory): """ Convert bank statements to YNAB format Args: - input_files (list): Optional list of specific files to process - If None, processes all files in current directory + input_files (list): List of specific files to process + If empty, processes all files in current directory """ current_directory = Path.cwd() - output_directory = current_directory / "YNAB_Outputs" + + if not output_directory: + output_directory = current_directory / "YNAB_Outputs" + logger.debug(f"No output directory set. Defaulting to {output_directory}") # Create output directory if it doesn't exist - output_directory.mkdir(exist_ok=True) + output_directory.mkdir(exist_ok=True, parents=True) # Get list of files to process if input_files: - print(f"Processing {len(input_files)} dragged file(s)...") + logger.info(f"Processing {len(input_files)} dragged file(s)...") files_to_process = [Path(f) for f in input_files if Path(f).exists()] else: - print("Processing all files in current directory...") + logger.info("Processing all files in current directory...") + logger.debug(f"Current directory is {current_directory}") files_to_process = [] # Collect all files matching any bank pattern for bank_config in BANKS.values(): @@ -249,17 +257,17 @@ def convert_bank_statements_to_ynab(input_files=None): # Process each file for file_path in files_to_process: if not file_path.exists(): - print(f"File not found: {file_path}") + logger.warning(f"File not found: {file_path}") continue # Find matching bank configuration bank_name, bank_config = find_bank_config(file_path.name) if not bank_config: - print(f"No bank configuration found for file: {file_path.name}") + logger.warning(f"No bank configuration found for file: {file_path.name}") continue - print(f"Processing file: {file_path} for {bank_name}") + logger.info(f"Processing file: {file_path} for {bank_name}") parse_function = bank_config["parse_function"] delimiter = bank_config.get("delimiter", ",") @@ -269,7 +277,7 @@ def convert_bank_statements_to_ynab(input_files=None): ynab_data = process_bank_statement(str(file_path), parse_function, delimiter, encoding) if ynab_data.empty: - print(f"No data processed for {file_path}") + logger.warning(f"No data processed for {file_path}") continue filename_placeholders = { @@ -295,22 +303,49 @@ def convert_bank_statements_to_ynab(input_files=None): # Export to CSV for YNAB import ynab_data.to_csv(output_file, index=False) - print(f"Data saved to {output_file}") + logger.info(f"Data saved to {output_file}") files_processed = True if not files_processed: - print("No files were processed. Make sure your files match the expected patterns.") + logger.warning("No files were processed. Make sure your files match the expected patterns.") if __name__ == "__main__": - # Check if files were dragged onto the script - if len(sys.argv) > 1: - # Files were dragged - process them - files = sys.argv[1:] - convert_bank_statements_to_ynab(files) - else: - # No files dragged - run normal directory processing - convert_bank_statements_to_ynab() - - # Keep window open on Mac so user can see results - input("\nPress Enter to close...") \ No newline at end of file + parser = argparse.ArgumentParser( + prog='YNAB', + description='Prepare bank transcripts for import to You Need A Budget', + ) + + parser.add_argument( + 'filenames', + type=Path, + nargs='*', + help='The files to process', + ) + + parser.add_argument( + '-o', '--output-dir', + type=Path, + default=None, + help='The location to store the converted files', + ) + + parser.add_argument( + '-v', '--verbose', + default=0, + action='count', + help='Increase logging verbosity', + ) + + args = parser.parse_args() + + if args.verbose <= 0: + log_level = logging.WARNING + elif args.verbose == 1: + log_level = logging.INFO + elif args.verbose >= 2: + log_level = logging.DEBUG + + logging.basicConfig(level=log_level) + + convert_bank_statements_to_ynab(args.filenames, args.output_dir) \ No newline at end of file