104 lines
3.2 KiB
Python
104 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from csv import DictWriter
|
|
from glob import glob
|
|
from ofxparse import OfxParser
|
|
from pathlib import Path
|
|
|
|
import os
|
|
import time
|
|
import watchdog.events
|
|
import watchdog.observers
|
|
|
|
DATE_FORMAT = "%d/%m/%Y"
|
|
WATCH_DIR = os.path.dirname(os.path.realpath(__file__))
|
|
PATTERN = '*.qfx'
|
|
BACKUP_DIR = 'Imported'
|
|
|
|
|
|
class Handler(watchdog.events.PatternMatchingEventHandler):
|
|
def __init__(self):
|
|
# Set the patterns for PatternMatchingEventHandler
|
|
watchdog.events.PatternMatchingEventHandler.__init__(self, patterns=['*.qfx'],
|
|
ignore_directories=True, case_sensitive=False)
|
|
|
|
@staticmethod
|
|
def write_csv(statement, out_file):
|
|
print("Writing: " + out_file)
|
|
fields = ['date', 'memo', 'category', 'amount', 'name']
|
|
with open(out_file, 'w') as f:
|
|
f.write("Date,Original Description,Category,Amount,Account Name")
|
|
f.write("\r\n")
|
|
writer = DictWriter(f, fieldnames=fields)
|
|
for line in statement:
|
|
writer.writerow(line)
|
|
|
|
@staticmethod
|
|
def get_statement_from_qfx(qfx):
|
|
balance = qfx.account.statement.balance
|
|
|
|
statement = []
|
|
credit_transactions = ['credit', 'dep', 'int']
|
|
debit_transactions = ['debit', 'atm', 'pos', 'xfer', 'check']
|
|
for transaction in qfx.account.statement.transactions:
|
|
amount = ""
|
|
balance = balance + transaction.amount
|
|
|
|
if transaction.payee.startswith("PENDING:"):
|
|
continue
|
|
|
|
line = {
|
|
'date': transaction.date.strftime(DATE_FORMAT),
|
|
'memo' : transaction.memo,
|
|
'category': 'Uncategorised',
|
|
'amount': transaction.amount,
|
|
'name': 'HSBC Everyday Global'
|
|
}
|
|
statement.append(line)
|
|
return statement
|
|
|
|
@staticmethod
|
|
def unique_path(directory, name_pattern):
|
|
counter = 0
|
|
while True:
|
|
counter += 1
|
|
path = directory / name_pattern.format(counter)
|
|
if not path.exists():
|
|
return path
|
|
|
|
def on_created(self, event):
|
|
qfx = OfxParser.parse(open(event.src_path, encoding="latin-1"), fail_fast=False)
|
|
statement = Handler.get_statement_from_qfx(qfx)
|
|
|
|
path = Path(event.src_path)
|
|
path.resolve()
|
|
|
|
out_file = str(path.parent / ('converted' + path.stem + '.csv'))
|
|
Handler.write_csv(statement, out_file)
|
|
|
|
#Now move the input file to backup
|
|
archive_file_dir = path.parent / BACKUP_DIR
|
|
archive_file = (path.stem + '{:04d}' + path.suffix)
|
|
destination = Handler.unique_path(archive_file_dir, archive_file)
|
|
|
|
if not archive_file_dir.exists():
|
|
archive_file_dir.mkdir()
|
|
|
|
if not destination.exists():
|
|
path.replace(destination)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
event_handler = Handler()
|
|
observer = watchdog.observers.Observer()
|
|
observer.schedule(event_handler, path=WATCH_DIR, recursive=False)
|
|
|
|
observer.start()
|
|
try:
|
|
while True:
|
|
time.sleep(1)
|
|
except KeyboardInterrupt:
|
|
observer.stop()
|
|
observer.join()
|